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] Revert 23295:4891f1f41ba5 and 23296:24346

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Revert 23295:4891f1f41ba5 and 23296:24346f749826
From: Xen patchbot-unstable <patchbot@xxxxxxx>
Date: Wed, 04 May 2011 16:50:18 +0100
Delivery-date: Wed, 04 May 2011 08:52:23 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/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 Keir Fraser <keir@xxxxxxx>
# Date 1304334040 -3600
# Node ID 10f27b8b3d63959c7a8e15299a7a398b7ff7f230
# Parent  24346f749826275540ab7bc95980355ec96c8cf8
Revert 23295:4891f1f41ba5 and 23296:24346f749826

Fails current lock checking mechanism in spinlock.c in debug=y builds.

Signed-off-by: Keir Fraser <keir@xxxxxxx>
---


diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/ia64/vmx/vmx_interrupt.c
--- a/xen/arch/ia64/vmx/vmx_interrupt.c Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/ia64/vmx/vmx_interrupt.c Mon May 02 12:00:40 2011 +0100
@@ -155,13 +155,13 @@
     /* dummy */
 }
 
-int msixtbl_pt_register(struct domain *d, struct pirq *pirq, uint64_t gtable)
+int msixtbl_pt_register(struct domain *d, int pirq, uint64_t gtable)
 {
     /* dummy */
     return -ENOSYS;
 }
 
-void msixtbl_pt_unregister(struct domain *d, struct pirq *pirq)
+void msixtbl_pt_unregister(struct domain *d, int pirq)
 {
     /* dummy */
 }
diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c     Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/ia64/xen/hypercall.c     Mon May 02 12:00:40 2011 +0100
@@ -65,11 +65,8 @@
 {
        if ( pirq < 0 || pirq >= NR_IRQS )
                return -EINVAL;
-       if ( d->arch.pirq_eoi_map ) {
-               spin_lock(&d->event_lock);
-               evtchn_unmask(pirq_to_evtchn(d, pirq));
-               spin_unlock(&d->event_lock);
-       }
+       if ( d->arch.pirq_eoi_map )
+               evtchn_unmask(d->pirq_to_evtchn[pirq]);
        return pirq_guest_eoi(d, pirq);
 }
 
diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/ia64/xen/irq.c
--- a/xen/arch/ia64/xen/irq.c   Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/ia64/xen/irq.c   Mon May 02 12:00:40 2011 +0100
@@ -363,17 +363,15 @@
     irq_desc_t         *desc = &irq_desc[irq];
     irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
     struct domain      *d;
-    struct pirq        *pirq;
     int                 i, already_pending = 0;
 
     for ( i = 0; i < action->nr_guests; i++ )
     {
         d = action->guest[i];
-        pirq = pirq_info(d, irq);
         if ( (action->ack_type != ACKTYPE_NONE) &&
-             !test_and_set_bool(pirq->masked) )
+             !test_and_set_bit(irq, &d->pirq_mask) )
             action->in_flight++;
-               if ( hvm_do_IRQ_dpci(d, pirq) )
+               if ( hvm_do_IRQ_dpci(d, irq) )
                {
                        if ( action->ack_type == ACKTYPE_NONE )
                        {
@@ -381,7 +379,7 @@
                                desc->status |= IRQ_INPROGRESS; /* cleared 
during hvm eoi */
                        }
                }
-               else if ( send_guest_pirq(d, pirq) &&
+               else if ( send_guest_pirq(d, irq) &&
                                (action->ack_type == ACKTYPE_NONE) )
                {
                        already_pending++;
@@ -425,23 +423,26 @@
     return ACKTYPE_NONE;
 }
 
-int pirq_guest_eoi(struct domain *d, struct pirq *pirq)
+int pirq_guest_eoi(struct domain *d, int irq)
 {
     irq_desc_t *desc;
     irq_guest_action_t *action;
 
+    if ( (irq < 0) || (irq >= NR_IRQS) )
+        return -EINVAL;
+
     desc = &irq_desc[irq];
     spin_lock_irq(&desc->lock);
     action = (irq_guest_action_t *)desc->action;
 
     if ( action->ack_type == ACKTYPE_NONE )
     {
-        ASSERT(!pirq->masked);
+        ASSERT(!test_bit(irq, d->pirq_mask));
         stop_timer(&irq_guest_eoi_timer[irq]);
         _irq_guest_eoi(desc);
     }
 
-    if ( test_and_clear_bool(pirq->masked) && (--action->in_flight == 0) )
+    if ( test_and_clear_bit(irq, &d->pirq_mask) && (--action->in_flight == 0) )
     {
         ASSERT(action->ack_type == ACKTYPE_UNMASK);
         desc->handler->end(irq);
@@ -454,27 +455,22 @@
 
 int pirq_guest_unmask(struct domain *d)
 {
-    unsigned int pirq = 0, n, i;
-    unsigned long indexes[16];
-    struct pirq *pirqs[ARRAY_SIZE(indexes)];
+    int            irq;
     shared_info_t *s = d->shared_info;
 
-    do {
-        n = radix_tree_gang_lookup(&d->pirq_tree, (void **)pirqs, pirq,
-                                   ARRAY_SIZE(pirqs), indexes);
-        for ( i = 0; i < n; ++i )
-        {
-            pirq = indexes[i];
-            if ( pirqs[i]->masked &&
-                 !test_bit(pirqs[i]->evtchn, &s->evtchn_mask[0]) )
-            pirq_guest_eoi(d, pirqs[i]);
-        }
-    } while ( ++pirq < d->nr_pirqs && n == ARRAY_SIZE(pirqs) );
+    for ( irq = find_first_bit(d->pirq_mask, NR_IRQS);
+          irq < NR_IRQS;
+          irq = find_next_bit(d->pirq_mask, NR_IRQS, irq+1) )
+    {
+        if ( !test_bit(d->pirq_to_evtchn[irq], &s->evtchn_mask[0]) )
+            pirq_guest_eoi(d, irq);
+
+    }
 
     return 0;
 }
 
-int pirq_guest_bind(struct vcpu *v, int irq, struct pirq *pirq, int will_share)
+int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
 {
     irq_desc_t         *desc = &irq_desc[irq];
     irq_guest_action_t *action;
@@ -558,7 +554,7 @@
     return rc;
 }
 
-void pirq_guest_unbind(struct domain *d, int irq, struct pirq *pirq)
+void pirq_guest_unbind(struct domain *d, int irq)
 {
     irq_desc_t         *desc = &irq_desc[irq];
     irq_guest_action_t *action;
@@ -576,7 +572,7 @@
     action->nr_guests--;
 
     if ( action->ack_type == ACKTYPE_UNMASK )
-        if ( test_and_clear_bool(pirq->masked) &&
+        if ( test_and_clear_bit(irq, &d->pirq_mask) &&
              (--action->in_flight == 0) )
             desc->handler->end(irq);
 
diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/x86/domain.c     Mon May 02 12:00:40 2011 +0100
@@ -608,8 +608,34 @@
         share_xen_page_with_guest(
             virt_to_page(d->shared_info), d, XENSHARE_writable);
 
-        if ( (rc = init_domain_irq_mapping(d)) != 0 )
+        d->arch.pirq_irq = xmalloc_array(int, d->nr_pirqs);
+        if ( !d->arch.pirq_irq )
             goto fail;
+        memset(d->arch.pirq_irq, 0,
+               d->nr_pirqs * sizeof(*d->arch.pirq_irq));
+
+        d->arch.irq_pirq = xmalloc_array(int, nr_irqs);
+        if ( !d->arch.irq_pirq )
+            goto fail;
+        memset(d->arch.irq_pirq, 0,
+               nr_irqs * sizeof(*d->arch.irq_pirq));
+
+        for ( i = 1; platform_legacy_irq(i); ++i )
+            if ( !IO_APIC_IRQ(i) )
+                d->arch.irq_pirq[i] = d->arch.pirq_irq[i] = i;
+
+        if ( is_hvm_domain(d) )
+        {
+            d->arch.pirq_emuirq = xmalloc_array(int, d->nr_pirqs);
+            d->arch.emuirq_pirq = xmalloc_array(int, nr_irqs);
+            if ( !d->arch.pirq_emuirq || !d->arch.emuirq_pirq )
+                goto fail;
+            for (i = 0; i < d->nr_pirqs; i++)
+                d->arch.pirq_emuirq[i] = IRQ_UNBOUND;
+            for (i = 0; i < nr_irqs; i++)
+                d->arch.emuirq_pirq[i] = IRQ_UNBOUND;
+        }
+
 
         if ( (rc = iommu_domain_init(d)) != 0 )
             goto fail;
@@ -644,7 +670,10 @@
  fail:
     d->is_dying = DOMDYING_dead;
     vmce_destroy_msr(d);
-    cleanup_domain_irq_mapping(d);
+    xfree(d->arch.pirq_irq);
+    xfree(d->arch.irq_pirq);
+    xfree(d->arch.pirq_emuirq);
+    xfree(d->arch.emuirq_pirq);
     free_xenheap_page(d->shared_info);
     if ( paging_initialised )
         paging_final_teardown(d);
@@ -696,7 +725,10 @@
 #endif
 
     free_xenheap_page(d->shared_info);
-    cleanup_domain_irq_mapping(d);
+    xfree(d->arch.pirq_irq);
+    xfree(d->arch.irq_pirq);
+    xfree(d->arch.pirq_emuirq);
+    xfree(d->arch.emuirq_pirq);
 }
 
 unsigned long pv_guest_cr4_fixup(const struct vcpu *v, unsigned long guest_cr4)
diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Mon May 02 12:00:40 2011 +0100
@@ -252,36 +252,32 @@
     pt_migrate(v);
 }
 
-static int hvm_migrate_pirq(struct domain *d, unsigned int pirq,
-                            struct hvm_pirq_dpci *pirq_dpci, void *arg)
+void hvm_migrate_pirqs(struct vcpu *v)
 {
-    struct vcpu *v = arg;
-
-    if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MACH_MSI) &&
-         (pirq_dpci->gmsi.dest_vcpu_id == v->vcpu_id) )
+    int pirq, irq;
+    struct irq_desc *desc;
+    struct domain *d = v->domain;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    
+    if ( !iommu_enabled || (hvm_irq_dpci == NULL) )
+       return;
+
+    spin_lock(&d->event_lock);
+    for ( pirq = find_first_bit(hvm_irq_dpci->mapping, d->nr_pirqs);
+          pirq < d->nr_pirqs;
+          pirq = find_next_bit(hvm_irq_dpci->mapping, d->nr_pirqs, pirq + 1) )
     {
-        struct irq_desc *desc =
-            pirq_spin_lock_irq_desc(d, dpci_pirq(pirq_dpci), NULL);
-
-        if ( !desc )
-            return 0;
-        ASSERT(MSI_IRQ(desc - irq_desc));
+        if ( !(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MACH_MSI) ||
+               (hvm_irq_dpci->mirq[pirq].gmsi.dest_vcpu_id != v->vcpu_id) )
+            continue;
+        desc = domain_spin_lock_irq_desc(v->domain, pirq, NULL);
+        if (!desc)
+            continue;
+        irq = desc - irq_desc;
+        ASSERT(MSI_IRQ(irq));
         irq_set_affinity(desc, cpumask_of(v->processor));
         spin_unlock_irq(&desc->lock);
     }
-
-    return 0;
-}
-
-void hvm_migrate_pirqs(struct vcpu *v)
-{
-    struct domain *d = v->domain;
-
-    if ( !iommu_enabled || !d->arch.hvm_domain.irq.dpci )
-       return;
-
-    spin_lock(&d->event_lock);
-    pt_pirq_iterate(d, hvm_migrate_pirq, v);
     spin_unlock(&d->event_lock);
 }
 
@@ -505,6 +501,8 @@
     return rc;
 }
 
+extern void msixtbl_pt_cleanup(struct domain *d);
+
 void hvm_domain_relinquish_resources(struct domain *d)
 {
     hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.ioreq);
diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/x86/hvm/irq.c    Mon May 02 12:00:40 2011 +0100
@@ -33,7 +33,7 @@
     int pirq = domain_emuirq_to_pirq(d, ioapic_gsi);
     if ( pirq != IRQ_UNBOUND )
     {
-        send_guest_pirq(d, pirq_info(d, pirq));
+        send_guest_pirq(d, pirq);
         return;
     }
     vioapic_irq_positive_edge(d, ioapic_gsi);
diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/x86/hvm/vmsi.c
--- a/xen/arch/x86/hvm/vmsi.c   Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/x86/hvm/vmsi.c   Mon May 02 12:00:40 2011 +0100
@@ -65,10 +65,11 @@
     }
 }
 
-int vmsi_deliver(struct domain *d, const struct hvm_pirq_dpci *pirq_dpci)
+int vmsi_deliver(struct domain *d, int pirq)
 {
-    uint32_t flags = pirq_dpci->gmsi.gflags;
-    int vector = pirq_dpci->gmsi.gvec;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    uint32_t flags = hvm_irq_dpci->mirq[pirq].gmsi.gflags;
+    int vector = hvm_irq_dpci->mirq[pirq].gmsi.gvec;
     uint8_t dest = (uint8_t)flags;
     uint8_t dest_mode = !!(flags & VMSI_DM_MASK);
     uint8_t delivery_mode = (flags & VMSI_DELIV_MASK) >> 
GLFAGS_SHIFT_DELIV_MODE;
@@ -81,7 +82,11 @@
                 "vector=%x trig_mode=%x\n",
                 dest, dest_mode, delivery_mode, vector, trig_mode);
 
-    ASSERT(pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI);
+    if ( !( hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_GUEST_MSI ) )
+    {
+        gdprintk(XENLOG_WARNING, "pirq %x not msi \n", pirq);
+        return 0;
+    }
 
     switch ( delivery_mode )
     {
@@ -344,7 +349,7 @@
     call_rcu(&entry->rcu, free_msixtbl_entry);
 }
 
-int msixtbl_pt_register(struct domain *d, struct pirq *pirq, uint64_t gtable)
+int msixtbl_pt_register(struct domain *d, int pirq, uint64_t gtable)
 {
     struct irq_desc *irq_desc;
     struct msi_desc *msi_desc;
@@ -353,7 +358,6 @@
     int r = -EINVAL;
 
     ASSERT(spin_is_locked(&pcidevs_lock));
-    ASSERT(spin_is_locked(&d->event_lock));
 
     /*
      * xmalloc() with irq_disabled causes the failure of check_lock() 
@@ -363,7 +367,7 @@
     if ( !new_entry )
         return -ENOMEM;
 
-    irq_desc = pirq_spin_lock_irq_desc(d, pirq, NULL);
+    irq_desc = domain_spin_lock_irq_desc(d, pirq, NULL);
     if ( !irq_desc )
     {
         xfree(new_entry);
@@ -400,7 +404,7 @@
     return r;
 }
 
-void msixtbl_pt_unregister(struct domain *d, struct pirq *pirq)
+void msixtbl_pt_unregister(struct domain *d, int pirq)
 {
     struct irq_desc *irq_desc;
     struct msi_desc *msi_desc;
@@ -408,9 +412,8 @@
     struct msixtbl_entry *entry;
 
     ASSERT(spin_is_locked(&pcidevs_lock));
-    ASSERT(spin_is_locked(&d->event_lock));
 
-    irq_desc = pirq_spin_lock_irq_desc(d, pirq, NULL);
+    irq_desc = domain_spin_lock_irq_desc(d, pirq, NULL);
     if ( !irq_desc )
         return;
 
@@ -444,7 +447,7 @@
     spin_unlock_irq(&irq_desc->lock);
 }
 
-void msixtbl_pt_cleanup(struct domain *d)
+void msixtbl_pt_cleanup(struct domain *d, int pirq)
 {
     struct msixtbl_entry *entry, *temp;
     unsigned long flags;
diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c        Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/x86/irq.c        Mon May 02 12:00:40 2011 +0100
@@ -814,7 +814,7 @@
         {
             struct domain *d = action->guest[i];
             unsigned int pirq = domain_irq_to_pirq(d, irq);
-            if ( test_and_clear_bool(pirq_info(d, pirq)->masked) )
+            if ( test_and_clear_bit(pirq, d->pirq_mask) )
                 action->in_flight--;
         }
     }
@@ -874,12 +874,11 @@
 
     for ( i = 0; i < action->nr_guests; i++ )
     {
-        struct pirq *pirq;
-
+        unsigned int pirq;
         d = action->guest[i];
-        pirq = pirq_info(d, domain_irq_to_pirq(d, irq));
+        pirq = domain_irq_to_pirq(d, irq);
         if ( (action->ack_type != ACKTYPE_NONE) &&
-             !test_and_set_bool(pirq->masked) )
+             !test_and_set_bit(pirq, d->pirq_mask) )
             action->in_flight++;
         if ( hvm_do_IRQ_dpci(d, pirq) )
         {
@@ -951,139 +950,6 @@
     return desc;
 }
 
-/*
- * Same with struct pirq already looked up, and d->event_lock already
- * held (thus the PIRQ <-> IRQ mapping can't change under our feet).
- */
-struct irq_desc *pirq_spin_lock_irq_desc(
-    struct domain *d, const struct pirq *pirq, unsigned long *pflags)
-{
-    int irq = pirq->arch.irq;
-    struct irq_desc *desc;
-    unsigned long flags;
-
-    ASSERT(spin_is_locked(&d->event_lock));
-
-    if ( irq <= 0 )
-        return NULL;
-
-    desc = irq_to_desc(irq);
-    spin_lock_irqsave(&desc->lock, flags);
-
-    if ( pflags )
-        *pflags = flags;
-
-    ASSERT(pirq == pirq_info(d, domain_irq_to_pirq(d, irq)));
-    ASSERT(irq == pirq->arch.irq);
-
-    return desc;
-}
-
-static int set_domain_irq_pirq(struct domain *d, int irq, int pirq)
-{
-    int err = radix_tree_insert(&d->arch.irq_pirq, irq, (void *)(long)pirq,
-                                NULL, NULL);
-
-    switch ( err )
-    {
-        struct pirq *info;
-
-    case -EEXIST:
-        *radix_tree_lookup_slot(&d->arch.irq_pirq, irq) = (void *)(long)pirq;
-        /* fall through */
-    case 0:
-        info = pirq_get_info(d, pirq);
-        if ( info )
-        {
-            info->arch.irq = irq;
-            return 0;
-        }
-        radix_tree_delete(&d->arch.irq_pirq, irq, NULL);
-        err = -ENOMEM;
-        break;
-    }
-
-    return err;
-}
-
-static void clear_domain_irq_pirq(struct domain *d, int irq, int pirq,
-                                  struct pirq *info)
-{
-    info->arch.irq = 0;
-    pirq_cleanup_check(info, d, pirq);
-    radix_tree_delete(&d->arch.irq_pirq, irq, NULL);
-}
-
-int init_domain_irq_mapping(struct domain *d)
-{
-    unsigned int i;
-    int err;
-
-    INIT_RADIX_TREE(&d->arch.irq_pirq, 0);
-    if ( is_hvm_domain(d) )
-        INIT_RADIX_TREE(&d->arch.hvm_domain.emuirq_pirq, 0);
-
-    for ( i = 1, err = 0; !err && platform_legacy_irq(i); ++i )
-        if ( !IO_APIC_IRQ(i) )
-            err = set_domain_irq_pirq(d, i, i);
-
-    return err;
-}
-
-static void irq_slot_free(void *unused)
-{
-}
-
-void cleanup_domain_irq_mapping(struct domain *d)
-{
-    radix_tree_destroy(&d->arch.irq_pirq, irq_slot_free, NULL);
-    if ( is_hvm_domain(d) )
-        radix_tree_destroy(&d->arch.hvm_domain.emuirq_pirq,
-                           irq_slot_free, NULL);
-}
-
-struct pirq *alloc_pirq_struct(struct domain *d)
-{
-    size_t sz = is_hvm_domain(d) ? sizeof(struct pirq) :
-                                   offsetof(struct pirq, arch.hvm);
-    struct pirq *pirq = xmalloc_bytes(sz);
-
-    if ( pirq )
-    {
-        memset(pirq, 0, sz);
-        if ( is_hvm_domain(d) )
-        {
-            pirq->arch.hvm.emuirq = IRQ_UNBOUND;
-            pt_pirq_init(d, &pirq->arch.hvm.dpci);
-        }
-    }
-
-    return pirq;
-}
-
-void (pirq_cleanup_check)(struct pirq *info, struct domain *d, int pirq)
-{
-    /*
-     * Check whether all fields have their default values, and delete
-     * the entry from the tree if so.
-     *
-     * NB: Common parts were already checked.
-     */
-    if ( info->arch.irq )
-        return;
-
-    if ( is_hvm_domain(d) )
-    {
-        if ( info->arch.hvm.emuirq != IRQ_UNBOUND )
-            return;
-        if ( !pt_pirq_cleanup_check(&info->arch.hvm.dpci) )
-            return;
-    }
-
-    if ( radix_tree_delete(&d->pirq_tree, pirq, NULL) != info )
-        BUG();
-}
-
 /* Flush all ready EOIs from the top of this CPU's pending-EOI stack. */
 static void flush_ready_eoi(void)
 {
@@ -1144,22 +1010,18 @@
     flush_ready_eoi();
 }
 
-void pirq_guest_eoi(struct domain *d, struct pirq *pirq)
+static void __pirq_guest_eoi(struct domain *d, int pirq)
 {
-    struct irq_desc *desc;
-
-    ASSERT(local_irq_is_enabled());
-    desc = pirq_spin_lock_irq_desc(d, pirq, NULL);
-    if ( desc )
-        desc_guest_eoi(d, desc, pirq);
-}
-
-void desc_guest_eoi(struct domain *d, struct irq_desc *desc, struct pirq *pirq)
-{
+    struct irq_desc         *desc;
     irq_guest_action_t *action;
     cpumask_t           cpu_eoi_map;
     int                 irq;
 
+    ASSERT(local_irq_is_enabled());
+    desc = domain_spin_lock_irq_desc(d, pirq, NULL);
+    if ( desc == NULL )
+        return;
+
     if ( !(desc->status & IRQ_GUEST) )
     {
         spin_unlock_irq(&desc->lock);
@@ -1171,12 +1033,12 @@
 
     if ( action->ack_type == ACKTYPE_NONE )
     {
-        ASSERT(!pirq->masked);
+        ASSERT(!test_bit(pirq, d->pirq_mask));
         stop_timer(&action->eoi_timer);
         _irq_guest_eoi(desc);
     }
 
-    if ( unlikely(!test_and_clear_bool(pirq->masked)) ||
+    if ( unlikely(!test_and_clear_bit(pirq, d->pirq_mask)) ||
          unlikely(--action->in_flight != 0) )
     {
         spin_unlock_irq(&desc->lock);
@@ -1211,23 +1073,27 @@
         on_selected_cpus(&cpu_eoi_map, set_eoi_ready, desc, 0);
 }
 
+int pirq_guest_eoi(struct domain *d, int irq)
+{
+    if ( (irq < 0) || (irq >= d->nr_pirqs) )
+        return -EINVAL;
+
+    __pirq_guest_eoi(d, irq);
+
+    return 0;
+}
+
 int pirq_guest_unmask(struct domain *d)
 {
-    unsigned int pirq = 0, n, i;
-    unsigned long indexes[16];
-    struct pirq *pirqs[ARRAY_SIZE(indexes)];
+    unsigned int irq, nr = d->nr_pirqs;
 
-    do {
-        n = radix_tree_gang_lookup(&d->pirq_tree, (void **)pirqs, pirq,
-                                   ARRAY_SIZE(pirqs), indexes);
-        for ( i = 0; i < n; ++i )
-        {
-            pirq = indexes[i];
-            if ( pirqs[i]->masked &&
-                 !test_bit(pirqs[i]->evtchn, &shared_info(d, evtchn_mask)) )
-                pirq_guest_eoi(d, pirqs[i]);
-        }
-    } while ( ++pirq < d->nr_pirqs && n == ARRAY_SIZE(pirqs) );
+    for ( irq = find_first_bit(d->pirq_mask, nr);
+          irq < nr;
+          irq = find_next_bit(d->pirq_mask, nr, irq+1) )
+    {
+        if ( !test_bit(d->pirq_to_evtchn[irq], &shared_info(d, evtchn_mask)) )
+            __pirq_guest_eoi(d, irq);
+    }
 
     return 0;
 }
@@ -1297,7 +1163,7 @@
     return shared;
 }
 
-int pirq_guest_bind(struct vcpu *v, int pirq, struct pirq *info, int 
will_share)
+int pirq_guest_bind(struct vcpu *v, int pirq, int will_share)
 {
     unsigned int        irq;
     struct irq_desc         *desc;
@@ -1309,7 +1175,7 @@
     BUG_ON(!local_irq_is_enabled());
 
  retry:
-    desc = pirq_spin_lock_irq_desc(v->domain, info, NULL);
+    desc = domain_spin_lock_irq_desc(v->domain, pirq, NULL);
     if ( desc == NULL )
     {
         rc = -EINVAL;
@@ -1410,7 +1276,7 @@
 }
 
 static irq_guest_action_t *__pirq_guest_unbind(
-    struct domain *d, int pirq, struct pirq *info, struct irq_desc *desc)
+    struct domain *d, int pirq, struct irq_desc *desc)
 {
     unsigned int        irq;
     irq_guest_action_t *action;
@@ -1439,13 +1305,13 @@
     switch ( action->ack_type )
     {
     case ACKTYPE_UNMASK:
-        if ( test_and_clear_bool(info->masked) &&
+        if ( test_and_clear_bit(pirq, d->pirq_mask) &&
              (--action->in_flight == 0) )
             desc->handler->end(irq);
         break;
     case ACKTYPE_EOI:
         /* NB. If #guests == 0 then we clear the eoi_map later on. */
-        if ( test_and_clear_bool(info->masked) &&
+        if ( test_and_clear_bit(pirq, d->pirq_mask) &&
              (--action->in_flight == 0) &&
              (action->nr_guests != 0) )
         {
@@ -1463,9 +1329,9 @@
 
     /*
      * The guest cannot re-bind to this IRQ until this function returns. So,
-     * when we have flushed this IRQ from ->masked, it should remain flushed.
+     * when we have flushed this IRQ from pirq_mask, it should remain flushed.
      */
-    BUG_ON(info->masked);
+    BUG_ON(test_bit(pirq, d->pirq_mask));
 
     if ( action->nr_guests != 0 )
         return NULL;
@@ -1503,7 +1369,7 @@
     return action;
 }
 
-void pirq_guest_unbind(struct domain *d, int pirq, struct pirq *info)
+void pirq_guest_unbind(struct domain *d, int pirq)
 {
     irq_guest_action_t *oldaction = NULL;
     struct irq_desc *desc;
@@ -1512,19 +1378,19 @@
     WARN_ON(!spin_is_locked(&d->event_lock));
 
     BUG_ON(!local_irq_is_enabled());
-    desc = pirq_spin_lock_irq_desc(d, info, NULL);
+    desc = domain_spin_lock_irq_desc(d, pirq, NULL);
 
     if ( desc == NULL )
     {
-        irq = -info->arch.irq;
+        irq = -domain_pirq_to_irq(d, pirq);
         BUG_ON(irq <= 0);
         desc = irq_to_desc(irq);
         spin_lock_irq(&desc->lock);
-        clear_domain_irq_pirq(d, irq, pirq, info);
+        d->arch.pirq_irq[pirq] = d->arch.irq_pirq[irq] = 0;
     }
     else
     {
-        oldaction = __pirq_guest_unbind(d, pirq, info, desc);
+        oldaction = __pirq_guest_unbind(d, pirq, desc);
     }
 
     spin_unlock_irq(&desc->lock);
@@ -1536,7 +1402,7 @@
     }
 }
 
-static int pirq_guest_force_unbind(struct domain *d, int irq, struct pirq 
*info)
+static int pirq_guest_force_unbind(struct domain *d, int irq)
 {
     struct irq_desc *desc;
     irq_guest_action_t *action, *oldaction = NULL;
@@ -1545,7 +1411,7 @@
     WARN_ON(!spin_is_locked(&d->event_lock));
 
     BUG_ON(!local_irq_is_enabled());
-    desc = pirq_spin_lock_irq_desc(d, info, NULL);
+    desc = domain_spin_lock_irq_desc(d, irq, NULL);
     BUG_ON(desc == NULL);
 
     if ( !(desc->status & IRQ_GUEST) )
@@ -1565,7 +1431,7 @@
         goto out;
 
     bound = 1;
-    oldaction = __pirq_guest_unbind(d, irq, info, desc);
+    oldaction = __pirq_guest_unbind(d, irq, desc);
 
  out:
     spin_unlock_irq(&desc->lock);
@@ -1579,13 +1445,6 @@
     return bound;
 }
 
-static inline bool_t is_free_pirq(const struct domain *d,
-                                  const struct pirq *pirq)
-{
-    return !pirq || (!pirq->arch.irq && (!is_hvm_domain(d) ||
-        pirq->arch.hvm.emuirq == IRQ_UNBOUND));
-}
-
 int get_free_pirq(struct domain *d, int type, int index)
 {
     int i;
@@ -1595,17 +1454,29 @@
     if ( type == MAP_PIRQ_TYPE_GSI )
     {
         for ( i = 16; i < nr_irqs_gsi; i++ )
-            if ( is_free_pirq(d, pirq_info(d, i)) )
-                return i;
+            if ( !d->arch.pirq_irq[i] )
+            {
+                if ( !is_hvm_domain(d) ||
+                        d->arch.pirq_emuirq[i] == IRQ_UNBOUND )
+                    break;
+            }
+        if ( i == nr_irqs_gsi )
+            return -ENOSPC;
     }
     else
     {
         for ( i = d->nr_pirqs - 1; i >= nr_irqs_gsi; i-- )
-            if ( is_free_pirq(d, pirq_info(d, i)) )
-                return i;
+            if ( !d->arch.pirq_irq[i] )
+            {
+                if ( !is_hvm_domain(d) ||
+                        d->arch.pirq_emuirq[i] == IRQ_UNBOUND )
+                    break;
+            }
+        if ( i < nr_irqs_gsi )
+            return -ENOSPC;
     }
 
-    return -ENOSPC;
+    return i;
 }
 
 int map_domain_pirq(
@@ -1673,23 +1544,15 @@
             dprintk(XENLOG_G_ERR, "dom%d: irq %d in use\n",
               d->domain_id, irq);
         desc->handler = &pci_msi_type;
-        ret = set_domain_irq_pirq(d, irq, pirq);
-        if ( !ret )
-        {
-            setup_msi_irq(pdev, msi_desc, irq);
-            spin_unlock_irqrestore(&desc->lock, flags);
-        }
-        else
-        {
-            desc->handler = &no_irq_type;
-            spin_unlock_irqrestore(&desc->lock, flags);
-            pci_disable_msi(msi_desc);
-        }
-    }
-    else
+        d->arch.pirq_irq[pirq] = irq;
+        d->arch.irq_pirq[irq] = pirq;
+        setup_msi_irq(pdev, msi_desc, irq);
+        spin_unlock_irqrestore(&desc->lock, flags);
+    } else
     {
         spin_lock_irqsave(&desc->lock, flags);
-        ret = set_domain_irq_pirq(d, irq, pirq);
+        d->arch.pirq_irq[pirq] = irq;
+        d->arch.irq_pirq[irq] = pirq;
         spin_unlock_irqrestore(&desc->lock, flags);
     }
 
@@ -1704,7 +1567,6 @@
     struct irq_desc *desc;
     int irq, ret = 0;
     bool_t forced_unbind;
-    struct pirq *info;
     struct msi_desc *msi_desc = NULL;
 
     if ( (pirq < 0) || (pirq >= d->nr_pirqs) )
@@ -1713,8 +1575,8 @@
     ASSERT(spin_is_locked(&pcidevs_lock));
     ASSERT(spin_is_locked(&d->event_lock));
 
-    info = pirq_info(d, pirq);
-    if ( !info || (irq = info->arch.irq) <= 0 )
+    irq = domain_pirq_to_irq(d, pirq);
+    if ( irq <= 0 )
     {
         dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n",
                 d->domain_id, pirq);
@@ -1722,7 +1584,7 @@
         goto done;
     }
 
-    forced_unbind = pirq_guest_force_unbind(d, pirq, info);
+    forced_unbind = pirq_guest_force_unbind(d, pirq);
     if ( forced_unbind )
         dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n",
                 d->domain_id, pirq);
@@ -1737,11 +1599,14 @@
     BUG_ON(irq != domain_pirq_to_irq(d, pirq));
 
     if ( !forced_unbind )
-        clear_domain_irq_pirq(d, irq, pirq, info);
+    {
+        d->arch.pirq_irq[pirq] = 0;
+        d->arch.irq_pirq[irq] = 0;
+    }
     else
     {
-        info->arch.irq = -irq;
-        *radix_tree_lookup_slot(&d->arch.irq_pirq, irq) = (void *)(long)-pirq;
+        d->arch.pirq_irq[pirq] = -irq;
+        d->arch.irq_pirq[irq] = -pirq;
     }
 
     spin_unlock_irqrestore(&desc->lock, flags);
@@ -1768,7 +1633,7 @@
     spin_lock(&d->event_lock);
 
     for ( i = 0; i < d->nr_pirqs; i++ )
-        if ( domain_pirq_to_irq(d, i) > 0 )
+        if ( d->arch.pirq_irq[i] > 0 )
             unmap_domain_pirq(d, i);
 
     spin_unlock(&d->event_lock);
@@ -1784,7 +1649,6 @@
     struct irq_cfg *cfg;
     irq_guest_action_t *action;
     struct domain *d;
-    const struct pirq *info;
     unsigned long flags;
 
     printk("Guest interrupt information:\n");
@@ -1819,18 +1683,20 @@
             {
                 d = action->guest[i];
                 pirq = domain_irq_to_pirq(d, irq);
-                info = pirq_info(d, pirq);
                 printk("%u:%3d(%c%c%c%c)",
                        d->domain_id, pirq,
-                       (test_bit(info->evtchn,
+                       (test_bit(d->pirq_to_evtchn[pirq],
                                  &shared_info(d, evtchn_pending)) ?
                         'P' : '-'),
-                       (test_bit(info->evtchn / BITS_PER_EVTCHN_WORD(d),
+                       (test_bit(d->pirq_to_evtchn[pirq] /
+                                 BITS_PER_EVTCHN_WORD(d),
                                  &vcpu_info(d->vcpu[0], evtchn_pending_sel)) ?
                         'S' : '-'),
-                       (test_bit(info->evtchn, &shared_info(d, evtchn_mask)) ?
+                       (test_bit(d->pirq_to_evtchn[pirq],
+                                 &shared_info(d, evtchn_mask)) ?
                         'M' : '-'),
-                       (info->masked ? 'M' : '-'));
+                       (test_bit(pirq, d->pirq_mask) ?
+                        'M' : '-'));
                 if ( i != action->nr_guests )
                     printk(",");
             }
@@ -1937,7 +1803,6 @@
 int map_domain_emuirq_pirq(struct domain *d, int pirq, int emuirq)
 {
     int old_emuirq = IRQ_UNBOUND, old_pirq = IRQ_UNBOUND;
-    struct pirq *info;
 
     ASSERT(spin_is_locked(&d->event_lock));
 
@@ -1964,30 +1829,10 @@
         return 0;
     }
 
-    info = pirq_get_info(d, pirq);
-    if ( !info )
-        return -ENOMEM;
-
+    d->arch.pirq_emuirq[pirq] = emuirq;
     /* do not store emuirq mappings for pt devices */
     if ( emuirq != IRQ_PT )
-    {
-        int err = radix_tree_insert(&d->arch.hvm_domain.emuirq_pirq, emuirq,
-                                    (void *)((long)pirq + 1), NULL, NULL);
-
-        switch ( err )
-        {
-        case 0:
-            break;
-        case -EEXIST:
-            *radix_tree_lookup_slot(&d->arch.hvm_domain.emuirq_pirq, emuirq) =
-                (void *)((long)pirq + 1);
-            break;
-        default:
-            pirq_cleanup_check(info, d, pirq);
-            return err;
-        }
-    }
-    info->arch.hvm.emuirq = emuirq;
+        d->arch.emuirq_pirq[emuirq] = pirq;
 
     return 0;
 }
@@ -1995,7 +1840,6 @@
 int unmap_domain_pirq_emuirq(struct domain *d, int pirq)
 {
     int emuirq, ret = 0;
-    struct pirq *info;
 
     if ( !is_hvm_domain(d) )
         return -EINVAL;
@@ -2014,22 +1858,24 @@
         goto done;
     }
 
-    info = pirq_info(d, pirq);
-    if ( info )
-    {
-        info->arch.hvm.emuirq = IRQ_UNBOUND;
-        pirq_cleanup_check(info, d, pirq);
-    }
+    d->arch.pirq_emuirq[pirq] = IRQ_UNBOUND;
     if ( emuirq != IRQ_PT )
-        radix_tree_delete(&d->arch.hvm_domain.emuirq_pirq, emuirq, NULL);
+        d->arch.emuirq_pirq[emuirq] = IRQ_UNBOUND;
 
  done:
     return ret;
 }
 
-bool_t hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq)
+int hvm_domain_use_pirq(struct domain *d, int pirq)
 {
-    return is_hvm_domain(d) &&
-           pirq->arch.hvm.emuirq != IRQ_UNBOUND &&
-           pirq->evtchn != 0;
+    int emuirq;
+    
+    if ( !is_hvm_domain(d) )
+        return 0;
+
+    emuirq = domain_pirq_to_emuirq(d, pirq);
+    if ( emuirq != IRQ_UNBOUND && d->pirq_to_evtchn[pirq] != 0 )
+        return 1;
+    else
+        return 0;
 }
diff -r 24346f749826 -r 10f27b8b3d63 xen/arch/x86/physdev.c
--- a/xen/arch/x86/physdev.c    Sun May 01 13:17:44 2011 +0100
+++ b/xen/arch/x86/physdev.c    Mon May 02 12:00:40 2011 +0100
@@ -258,28 +258,20 @@
     {
     case PHYSDEVOP_eoi: {
         struct physdev_eoi eoi;
-        struct pirq *pirq;
-
         ret = -EFAULT;
         if ( copy_from_guest(&eoi, arg, 1) != 0 )
             break;
         ret = -EINVAL;
         if ( eoi.irq >= v->domain->nr_pirqs )
             break;
-        spin_lock(&v->domain->event_lock);
-        pirq = pirq_info(v->domain, eoi.irq);
-        if ( !pirq ) {
-            spin_unlock(&v->domain->event_lock);
-            break;
-        }
         if ( !is_hvm_domain(v->domain) &&
              v->domain->arch.pv_domain.pirq_eoi_map )
-            evtchn_unmask(pirq->evtchn);
+            evtchn_unmask(v->domain->pirq_to_evtchn[eoi.irq]);
         if ( !is_hvm_domain(v->domain) ||
-             pirq->arch.hvm.emuirq == IRQ_PT )
-            pirq_guest_eoi(v->domain, pirq);
-        spin_unlock(&v->domain->event_lock);
-        ret = 0;
+             domain_pirq_to_emuirq(v->domain, eoi.irq) == IRQ_PT )
+            ret = pirq_guest_eoi(v->domain, eoi.irq);
+        else
+            ret = 0;
         break;
     }
 
@@ -572,23 +564,11 @@
             break;
 
         spin_lock(&d->event_lock);
-        ret = get_free_pirq(d, out.type, 0);
-        if ( ret >= 0 )
-        {
-            struct pirq *info = pirq_get_info(d, ret);
-
-            if ( info )
-                info->arch.irq = PIRQ_ALLOCATED;
-            else
-                ret = -ENOMEM;
-        }
+        out.pirq = get_free_pirq(d, out.type, 0);
+        d->arch.pirq_irq[out.pirq] = PIRQ_ALLOCATED;
         spin_unlock(&d->event_lock);
 
-        if ( ret >= 0 )
-        {
-            out.pirq = ret;
-            ret = copy_to_guest(arg, &out, 1) ? -EFAULT : 0;
-        }
+        ret = copy_to_guest(arg, &out, 1) ? -EFAULT : 0;
 
         rcu_unlock_domain(d);
         break;
diff -r 24346f749826 -r 10f27b8b3d63 xen/common/domain.c
--- a/xen/common/domain.c       Sun May 01 13:17:44 2011 +0100
+++ b/xen/common/domain.c       Mon May 02 12:00:40 2011 +0100
@@ -290,7 +290,13 @@
         if ( d->nr_pirqs > nr_irqs )
             d->nr_pirqs = nr_irqs;
 
-        INIT_RADIX_TREE(&d->pirq_tree, 0);
+        d->pirq_to_evtchn = xmalloc_array(u16, d->nr_pirqs);
+        d->pirq_mask = xmalloc_array(
+            unsigned long, BITS_TO_LONGS(d->nr_pirqs));
+        if ( (d->pirq_to_evtchn == NULL) || (d->pirq_mask == NULL) )
+            goto fail;
+        memset(d->pirq_to_evtchn, 0, d->nr_pirqs * sizeof(*d->pirq_to_evtchn));
+        bitmap_zero(d->pirq_mask, d->nr_pirqs);
 
         if ( evtchn_init(d) != 0 )
             goto fail;
@@ -340,7 +346,6 @@
     {
         evtchn_destroy(d);
         evtchn_destroy_final(d);
-        radix_tree_destroy(&d->pirq_tree, free_pirq_struct, NULL);
     }
     if ( init_status & INIT_rangeset )
         rangeset_domain_destroy(d);
@@ -348,6 +353,8 @@
         watchdog_domain_destroy(d);
     if ( init_status & INIT_xsm )
         xsm_free_security_domain(d);
+    xfree(d->pirq_mask);
+    xfree(d->pirq_to_evtchn);
     free_cpumask_var(d->domain_dirty_cpumask);
     free_domain_struct(d);
     return NULL;
@@ -673,7 +680,8 @@
 
     evtchn_destroy_final(d);
 
-    radix_tree_destroy(&d->pirq_tree, free_pirq_struct, NULL);
+    xfree(d->pirq_mask);
+    xfree(d->pirq_to_evtchn);
 
     xsm_free_security_domain(d);
     free_cpumask_var(d->domain_dirty_cpumask);
@@ -955,20 +963,6 @@
     return -ENOSYS;
 }
 
-struct pirq *pirq_get_info(struct domain *d, int pirq)
-{
-    struct pirq *info = pirq_info(d, pirq);
-
-    if ( !info && (info = alloc_pirq_struct(d)) != NULL &&
-         radix_tree_insert(&d->pirq_tree, pirq, info, NULL, NULL) )
-    {
-         free_pirq_struct(info);
-         info = NULL;
-    }
-
-    return info;
-}
-
 struct migrate_info {
     long (*func)(void *data);
     void *data;
diff -r 24346f749826 -r 10f27b8b3d63 xen/common/event_channel.c
--- a/xen/common/event_channel.c        Sun May 01 13:17:44 2011 +0100
+++ b/xen/common/event_channel.c        Mon May 02 12:00:40 2011 +0100
@@ -325,7 +325,6 @@
     struct evtchn *chn;
     struct domain *d = current->domain;
     struct vcpu   *v = d->vcpu[0];
-    struct pirq   *info;
     int            port, pirq = bind->pirq;
     long           rc;
 
@@ -337,7 +336,7 @@
 
     spin_lock(&d->event_lock);
 
-    if ( pirq_to_evtchn(d, pirq) != 0 )
+    if ( d->pirq_to_evtchn[pirq] != 0 )
         ERROR_EXIT(-EEXIST);
 
     if ( (port = get_free_port(d)) < 0 )
@@ -345,18 +344,14 @@
 
     chn = evtchn_from_port(d, port);
 
-    info = pirq_get_info(d, pirq);
-    if ( !info )
-        ERROR_EXIT(-ENOMEM);
-    info->evtchn = port;
+    d->pirq_to_evtchn[pirq] = port;
     rc = (!is_hvm_domain(d)
-          ? pirq_guest_bind(v, pirq, info,
-                            !!(bind->flags & BIND_PIRQ__WILL_SHARE))
+          ? pirq_guest_bind(
+              v, pirq, !!(bind->flags & BIND_PIRQ__WILL_SHARE))
           : 0);
     if ( rc != 0 )
     {
-        info->evtchn = 0;
-        pirq_cleanup_check(info, d, pirq);
+        d->pirq_to_evtchn[pirq] = 0;
         goto out;
     }
 
@@ -409,18 +404,12 @@
     case ECS_UNBOUND:
         break;
 
-    case ECS_PIRQ: {
-        struct pirq *pirq = pirq_info(d1, chn1->u.pirq.irq);
-
-        if ( !pirq )
-            break;
+    case ECS_PIRQ:
         if ( !is_hvm_domain(d1) )
-            pirq_guest_unbind(d1, chn1->u.pirq.irq, pirq);
-        pirq->evtchn = 0;
-        pirq_cleanup_check(pirq, d1, chn1->u.pirq.irq);
+            pirq_guest_unbind(d1, chn1->u.pirq.irq);
+        d1->pirq_to_evtchn[chn1->u.pirq.irq] = 0;
         unlink_pirq_port(chn1, d1->vcpu[chn1->notify_vcpu_id]);
         break;
-    }
 
     case ECS_VIRQ:
         for_each_vcpu ( d1, v )
@@ -670,9 +659,9 @@
     spin_unlock_irqrestore(&v->virq_lock, flags);
 }
 
-int send_guest_pirq(struct domain *d, const struct pirq *pirq)
+int send_guest_pirq(struct domain *d, int pirq)
 {
-    int port;
+    int port = d->pirq_to_evtchn[pirq];
     struct evtchn *chn;
 
     /*
@@ -681,7 +670,7 @@
      * HVM guests: Port is legitimately zero when the guest disables the
      *     emulated interrupt/evtchn.
      */
-    if ( pirq == NULL || (port = pirq->evtchn) == 0 )
+    if ( port == 0 )
     {
         BUG_ON(!is_hvm_domain(d));
         return 0;
@@ -823,10 +812,13 @@
     struct domain *d = current->domain;
     struct vcpu   *v;
 
-    ASSERT(spin_is_locked(&d->event_lock));
+    spin_lock(&d->event_lock);
 
     if ( unlikely(!port_is_valid(d, port)) )
+    {
+        spin_unlock(&d->event_lock);
         return -EINVAL;
+    }
 
     v = d->vcpu[evtchn_from_port(d, port)->notify_vcpu_id];
 
@@ -842,6 +834,8 @@
         vcpu_mark_events_pending(v);
     }
 
+    spin_unlock(&d->event_lock);
+
     return 0;
 }
 
@@ -966,9 +960,7 @@
         struct evtchn_unmask unmask;
         if ( copy_from_guest(&unmask, arg, 1) != 0 )
             return -EFAULT;
-        spin_lock(&current->domain->event_lock);
         rc = evtchn_unmask(unmask.port);
-        spin_unlock(&current->domain->event_lock);
         break;
     }
 
diff -r 24346f749826 -r 10f27b8b3d63 xen/common/radix-tree.c
--- a/xen/common/radix-tree.c   Sun May 01 13:17:44 2011 +0100
+++ b/xen/common/radix-tree.c   Mon May 02 12:00:40 2011 +0100
@@ -26,6 +26,7 @@
  * o tagging code removed
  * o radix_tree_insert has func parameter for dynamic data struct allocation
  * o radix_tree_destroy added (including recursive helper function)
+ * o __init functions must be called explicitly
  * o other include files adapted to Xen
  */
 
@@ -34,7 +35,6 @@
 #include <xen/lib.h>
 #include <xen/types.h>
 #include <xen/errno.h>
-#include <xen/xmalloc.h>
 #include <xen/radix-tree.h>
 #include <asm/cache.h>
 
@@ -49,18 +49,6 @@
     return height_to_maxindex[height];
 }
 
-static struct radix_tree_node *_node_alloc(void *unused)
-{
-    struct radix_tree_node *node = xmalloc(struct radix_tree_node);
-
-    return node ? memset(node, 0, sizeof(*node)) : node;
-}
-
-static void _node_free(struct radix_tree_node *node)
-{
-    xfree(node);
-}
-
 /*
  * Extend a radix tree so it can store key @index.
  */
@@ -112,9 +100,6 @@
     int offset;
     int error;
 
-    if (!node_alloc)
-        node_alloc = _node_alloc;
-
     /* Make sure the tree is high enough.  */
     if (index > radix_tree_maxindex(root->height)) {
         error = radix_tree_extend(root, index, node_alloc, arg);
@@ -225,8 +210,7 @@
 
 static unsigned int
 __lookup(struct radix_tree_root *root, void **results, unsigned long index,
-         unsigned int max_items, unsigned long *indexes,
-         unsigned long *next_index)
+         unsigned int max_items, unsigned long *next_index)
 {
     unsigned int nr_found = 0;
     unsigned int shift, height;
@@ -236,11 +220,8 @@
     height = root->height;
     if (index > radix_tree_maxindex(height))
         if (height == 0) {
-            if (root->rnode && index == 0) {
-                if (indexes)
-                    indexes[nr_found] = index;
+            if (root->rnode && index == 0)
                 results[nr_found++] = root->rnode;
-            }
             goto out;
         }
 
@@ -269,8 +250,6 @@
     for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
         index++;
         if (slot->slots[i]) {
-            if (indexes)
-                indexes[nr_found] = index - 1;
             results[nr_found++] = slot->slots[i];
             if (nr_found == max_items)
                 goto out;
@@ -287,7 +266,6 @@
  * @results: where the results of the lookup are placed
  * @first_index: start the lookup from this key
  * @max_items: place up to this many items at *results
- * @indexes: (optional) array to store indexes of items.
  *
  * Performs an index-ascending scan of the tree for present items.  Places
  * them at *@results and returns the number of items which were placed at
@@ -297,8 +275,7 @@
  */
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
-                       unsigned long first_index, unsigned int max_items,
-                       unsigned long *indexes)
+                       unsigned long first_index, unsigned int max_items)
 {
     const unsigned long max_index = radix_tree_maxindex(root->height);
     unsigned long cur_index = first_index;
@@ -311,7 +288,7 @@
         if (cur_index > max_index)
             break;
         nr_found = __lookup(root, results + ret, cur_index,
-                            max_items - ret, indexes + ret, &next_index);
+                            max_items - ret, &next_index);
         ret += nr_found;
         if (next_index == 0)
             break;
@@ -359,9 +336,6 @@
     unsigned int height, shift;
     int offset;
 
-    if (!node_free)
-        node_free = _node_free;
-
     height = root->height;
     if (index > radix_tree_maxindex(height))
         goto out;
@@ -446,8 +420,6 @@
     if (root->height == 0)
         slot_free(root->rnode);
     else {
-        if (!node_free)
-            node_free = _node_free;
         radix_tree_node_destroy(root->rnode, root->height,
                                 slot_free, node_free);
         node_free(root->rnode);
@@ -468,14 +440,10 @@
     return index;
 }
 
-static int __init radix_tree_init(void)
+void __init radix_tree_init(void)
 {
     unsigned int i;
 
     for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++)
         height_to_maxindex[i] = __maxindex(i);
-
-    return 0;
 }
-/* pre-SMP just so it runs before 'normal' initcalls */
-presmp_initcall(radix_tree_init);
diff -r 24346f749826 -r 10f27b8b3d63 xen/common/tmem.c
--- a/xen/common/tmem.c Sun May 01 13:17:44 2011 +0100
+++ b/xen/common/tmem.c Mon May 02 12:00:40 2011 +0100
@@ -2925,6 +2925,7 @@
     if ( !tmh_enabled() )
         return 0;
 
+    radix_tree_init();
     if ( tmh_dedup_enabled() )
         for (i = 0; i < 256; i++ )
         {
diff -r 24346f749826 -r 10f27b8b3d63 xen/drivers/passthrough/io.c
--- a/xen/drivers/passthrough/io.c      Sun May 01 13:17:44 2011 +0100
+++ b/xen/drivers/passthrough/io.c      Mon May 02 12:00:40 2011 +0100
@@ -35,28 +35,18 @@
     return !(flags & (HVM_IRQ_DPCI_GUEST_MSI | HVM_IRQ_DPCI_TRANSLATE));
 }
 
-static int pt_irq_guest_eoi(struct domain *d, unsigned int pirq,
-                            struct hvm_pirq_dpci *pirq_dpci, void *arg)
-{
-    if ( __test_and_clear_bit(_HVM_IRQ_DPCI_EOI_LATCH_SHIFT,
-                              &pirq_dpci->flags) )
-    {
-        pirq_dpci->masked = 0;
-        pirq_dpci->pending = 0;
-        pirq_guest_eoi(d, dpci_pirq(pirq_dpci));
-    }
-
-    return 0;
-}
-
 static void pt_irq_time_out(void *data)
 {
-    struct hvm_pirq_dpci *irq_map = data;
-    unsigned int guest_gsi;
+    struct hvm_mirq_dpci_mapping *irq_map = data;
+    unsigned int guest_gsi, machine_gsi = 0;
     struct hvm_irq_dpci *dpci = NULL;
     struct dev_intx_gsi_link *digl;
     struct hvm_girq_dpci_mapping *girq;
     uint32_t device, intx;
+    unsigned int nr_pirqs = irq_map->dom->nr_pirqs;
+    DECLARE_BITMAP(machine_gsi_map, nr_pirqs);
+
+    bitmap_zero(machine_gsi_map, nr_pirqs);
 
     spin_lock(&irq_map->dom->event_lock);
 
@@ -67,18 +57,32 @@
         guest_gsi = digl->gsi;
         list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )
         {
-            struct pirq *pirq = pirq_info(irq_map->dom, girq->machine_gsi);
-
-            pirq_dpci(pirq)->flags |= HVM_IRQ_DPCI_EOI_LATCH;
+            machine_gsi = girq->machine_gsi;
+            set_bit(machine_gsi, machine_gsi_map);
         }
         device = digl->device;
         intx = digl->intx;
         hvm_pci_intx_deassert(irq_map->dom, device, intx);
     }
 
-    pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL);
+    for ( machine_gsi = find_first_bit(machine_gsi_map, nr_pirqs);
+          machine_gsi < nr_pirqs;
+          machine_gsi = find_next_bit(machine_gsi_map, nr_pirqs,
+                                      machine_gsi + 1) )
+    {
+        clear_bit(machine_gsi, dpci->dirq_mask);
+        dpci->mirq[machine_gsi].pending = 0;
+    }
 
     spin_unlock(&irq_map->dom->event_lock);
+
+    for ( machine_gsi = find_first_bit(machine_gsi_map, nr_pirqs);
+          machine_gsi < nr_pirqs;
+          machine_gsi = find_next_bit(machine_gsi_map, nr_pirqs,
+                                      machine_gsi + 1) )
+    {
+        pirq_guest_eoi(irq_map->dom, machine_gsi);
+    }
 }
 
 struct hvm_irq_dpci *domain_get_irq_dpci(const struct domain *d)
@@ -91,6 +95,10 @@
 
 void free_hvm_irq_dpci(struct hvm_irq_dpci *dpci)
 {
+    xfree(dpci->mirq);
+    xfree(dpci->dirq_mask);
+    xfree(dpci->mapping);
+    xfree(dpci->hvm_timer);
     xfree(dpci);
 }
 
@@ -98,9 +106,7 @@
     struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
 {
     struct hvm_irq_dpci *hvm_irq_dpci = NULL;
-    struct hvm_pirq_dpci *pirq_dpci;
-    struct pirq *info;
-    uint32_t guest_gsi;
+    uint32_t machine_gsi, guest_gsi;
     uint32_t device, intx, link;
     struct dev_intx_gsi_link *digl;
     struct hvm_girq_dpci_mapping *girq;
@@ -123,45 +129,63 @@
         memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci));
         tasklet_init(&hvm_irq_dpci->dirq_tasklet,
                      hvm_dirq_assist, (unsigned long)d);
+        hvm_irq_dpci->mirq = xmalloc_array(struct hvm_mirq_dpci_mapping,
+                                           d->nr_pirqs);
+        hvm_irq_dpci->dirq_mask = xmalloc_array(unsigned long,
+                                                BITS_TO_LONGS(d->nr_pirqs));
+        hvm_irq_dpci->mapping = xmalloc_array(unsigned long,
+                                              BITS_TO_LONGS(d->nr_pirqs));
+        hvm_irq_dpci->hvm_timer = xmalloc_array(struct timer, d->nr_pirqs);
+        if ( !hvm_irq_dpci->mirq ||
+             !hvm_irq_dpci->dirq_mask ||
+             !hvm_irq_dpci->mapping ||
+             !hvm_irq_dpci->hvm_timer)
+        {
+            spin_unlock(&d->event_lock);
+            free_hvm_irq_dpci(hvm_irq_dpci);
+            return -ENOMEM;
+        }
+        memset(hvm_irq_dpci->mirq, 0,
+               d->nr_pirqs * sizeof(*hvm_irq_dpci->mirq));
+        bitmap_zero(hvm_irq_dpci->dirq_mask, d->nr_pirqs);
+        bitmap_zero(hvm_irq_dpci->mapping, d->nr_pirqs);
+        memset(hvm_irq_dpci->hvm_timer, 0,
+                d->nr_pirqs * sizeof(*hvm_irq_dpci->hvm_timer));
+        for ( int i = 0; i < d->nr_pirqs; i++ ) {
+            INIT_LIST_HEAD(&hvm_irq_dpci->mirq[i].digl_list);
+            hvm_irq_dpci->mirq[i].gmsi.dest_vcpu_id = -1;
+        }
         for ( int i = 0; i < NR_HVM_IRQS; i++ )
             INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]);
 
         d->arch.hvm_domain.irq.dpci = hvm_irq_dpci;
     }
 
-    info = pirq_get_info(d, pirq);
-    if ( !info )
-    {
-        spin_unlock(&d->event_lock);
-        return -ENOMEM;
-    }
-    pirq_dpci = pirq_dpci(info);
-
     if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI )
     {
         uint8_t dest, dest_mode;
         int dest_vcpu_id;
 
-        if ( !(pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
+        if ( !test_and_set_bit(pirq, hvm_irq_dpci->mapping))
         {
-            pirq_dpci->flags = HVM_IRQ_DPCI_MAPPED | HVM_IRQ_DPCI_MACH_MSI |
-                               HVM_IRQ_DPCI_GUEST_MSI;
-            pirq_dpci->gmsi.gvec = pt_irq_bind->u.msi.gvec;
-            pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
+            hvm_irq_dpci->mirq[pirq].flags = HVM_IRQ_DPCI_MACH_MSI |
+                                             HVM_IRQ_DPCI_GUEST_MSI;
+            hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec;
+            hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags;
             /* bind after hvm_irq_dpci is setup to avoid race with irq 
handler*/
-            rc = pirq_guest_bind(d->vcpu[0], pirq, info, 0);
+            rc = pirq_guest_bind(d->vcpu[0], pirq, 0);
             if ( rc == 0 && pt_irq_bind->u.msi.gtable )
             {
-                rc = msixtbl_pt_register(d, info, pt_irq_bind->u.msi.gtable);
+                rc = msixtbl_pt_register(d, pirq, pt_irq_bind->u.msi.gtable);
                 if ( unlikely(rc) )
-                    pirq_guest_unbind(d, pirq, info);
+                    pirq_guest_unbind(d, pirq);
             }
             if ( unlikely(rc) )
             {
-                pirq_dpci->gmsi.gflags = 0;
-                pirq_dpci->gmsi.gvec = 0;
-                pirq_dpci->flags = 0;
-                pirq_cleanup_check(info, d, pirq);
+                hvm_irq_dpci->mirq[pirq].gmsi.gflags = 0;
+                hvm_irq_dpci->mirq[pirq].gmsi.gvec = 0;
+                hvm_irq_dpci->mirq[pirq].flags = 0;
+                clear_bit(pirq, hvm_irq_dpci->mapping);
                 spin_unlock(&d->event_lock);
                 return rc;
             }
@@ -170,33 +194,34 @@
         {
             uint32_t mask = HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_MSI;
 
-            if ( (pirq_dpci->flags & mask) != mask)
+            if ( (hvm_irq_dpci->mirq[pirq].flags & mask) != mask)
             {
                    spin_unlock(&d->event_lock);
                    return -EBUSY;
             }
 
             /* if pirq is already mapped as vmsi, update the guest data/addr */
-            if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
-                 pirq_dpci->gmsi.gflags != pt_irq_bind->u.msi.gflags) {
+            if ( hvm_irq_dpci->mirq[pirq].gmsi.gvec != pt_irq_bind->u.msi.gvec 
||
+                    hvm_irq_dpci->mirq[pirq].gmsi.gflags != 
pt_irq_bind->u.msi.gflags) {
                 /* Directly clear pending EOIs before enabling new MSI info. */
-                pirq_guest_eoi(d, info);
+                pirq_guest_eoi(d, pirq);
 
-                pirq_dpci->gmsi.gvec = pt_irq_bind->u.msi.gvec;
-                pirq_dpci->gmsi.gflags = pt_irq_bind->u.msi.gflags;
+                hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec;
+                hvm_irq_dpci->mirq[pirq].gmsi.gflags = 
pt_irq_bind->u.msi.gflags;
             }
         }
         /* Caculate dest_vcpu_id for MSI-type pirq migration */
-        dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;
-        dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);
+        dest = hvm_irq_dpci->mirq[pirq].gmsi.gflags & VMSI_DEST_ID_MASK;
+        dest_mode = !!(hvm_irq_dpci->mirq[pirq].gmsi.gflags & VMSI_DM_MASK);
         dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
-        pirq_dpci->gmsi.dest_vcpu_id = dest_vcpu_id;
+        hvm_irq_dpci->mirq[pirq].gmsi.dest_vcpu_id = dest_vcpu_id;
         spin_unlock(&d->event_lock);
         if ( dest_vcpu_id >= 0 )
             hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]);
     }
     else
     {
+        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);
@@ -222,51 +247,50 @@
         digl->intx = intx;
         digl->gsi = guest_gsi;
         digl->link = link;
-        list_add_tail(&digl->list, &pirq_dpci->digl_list);
+        list_add_tail(&digl->list,
+                      &hvm_irq_dpci->mirq[machine_gsi].digl_list);
 
         girq->device = device;
         girq->intx = intx;
-        girq->machine_gsi = pirq;
+        girq->machine_gsi = machine_gsi;
         list_add_tail(&girq->list, &hvm_irq_dpci->girq[guest_gsi]);
 
         /* Bind the same mirq once in the same domain */
-        if ( !(pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
+        if ( !test_and_set_bit(machine_gsi, hvm_irq_dpci->mapping))
         {
             unsigned int share;
 
-            pirq_dpci->dom = d;
+            hvm_irq_dpci->mirq[machine_gsi].dom = d;
             if ( pt_irq_bind->irq_type == PT_IRQ_TYPE_MSI_TRANSLATE )
             {
-                pirq_dpci->flags = HVM_IRQ_DPCI_MAPPED |
-                                   HVM_IRQ_DPCI_MACH_MSI |
-                                   HVM_IRQ_DPCI_GUEST_PCI |
-                                   HVM_IRQ_DPCI_TRANSLATE;
+                hvm_irq_dpci->mirq[machine_gsi].flags = HVM_IRQ_DPCI_MACH_MSI |
+                                                        HVM_IRQ_DPCI_GUEST_PCI 
|
+                                                        HVM_IRQ_DPCI_TRANSLATE;
                 share = 0;
             }
             else    /* PT_IRQ_TYPE_PCI */
             {
-                pirq_dpci->flags = HVM_IRQ_DPCI_MAPPED |
-                                   HVM_IRQ_DPCI_MACH_PCI |
-                                   HVM_IRQ_DPCI_GUEST_PCI;
+                hvm_irq_dpci->mirq[machine_gsi].flags = HVM_IRQ_DPCI_MACH_PCI |
+                                                        HVM_IRQ_DPCI_GUEST_PCI;
                 share = BIND_PIRQ__WILL_SHARE;
             }
 
             /* Init timer before binding */
-            if ( pt_irq_need_timer(pirq_dpci->flags) )
-                init_timer(&pirq_dpci->timer, pt_irq_time_out, pirq_dpci, 0);
+            if ( pt_irq_need_timer(hvm_irq_dpci->mirq[machine_gsi].flags) )
+                init_timer(&hvm_irq_dpci->hvm_timer[machine_gsi],
+                           pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 
0);
             /* Deal with gsi for legacy devices */
-            rc = pirq_guest_bind(d->vcpu[0], pirq, info, share);
+            rc = pirq_guest_bind(d->vcpu[0], machine_gsi, share);
             if ( unlikely(rc) )
             {
-                if ( pt_irq_need_timer(pirq_dpci->flags) )
-                    kill_timer(&pirq_dpci->timer);
-                pirq_dpci->dom = NULL;
+                if ( pt_irq_need_timer(hvm_irq_dpci->mirq[machine_gsi].flags) )
+                    kill_timer(&hvm_irq_dpci->hvm_timer[machine_gsi]);
+                hvm_irq_dpci->mirq[machine_gsi].dom = NULL;
+                clear_bit(machine_gsi, hvm_irq_dpci->mapping);
                 list_del(&girq->list);
                 xfree(girq);
                 list_del(&digl->list);
                 hvm_irq_dpci->link_cnt[link]--;
-                pirq_dpci->flags = 0;
-                pirq_cleanup_check(info, d, pirq);
                 spin_unlock(&d->event_lock);
                 xfree(digl);
                 return rc;
@@ -278,7 +302,7 @@
         if ( iommu_verbose )
             dprintk(VTDPREFIX,
                     "d%d: bind: m_gsi=%u g_gsi=%u device=%u intx=%u\n",
-                    d->domain_id, pirq, guest_gsi, device, intx);
+                    d->domain_id, machine_gsi, guest_gsi, device, intx);
     }
     return 0;
 }
@@ -287,12 +311,11 @@
     struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
 {
     struct hvm_irq_dpci *hvm_irq_dpci = NULL;
-    struct hvm_pirq_dpci *pirq_dpci;
     uint32_t machine_gsi, guest_gsi;
     uint32_t device, intx, link;
-    struct dev_intx_gsi_link *digl, *tmp;
+    struct list_head *digl_list, *tmp;
+    struct dev_intx_gsi_link *digl;
     struct hvm_girq_dpci_mapping *girq;
-    struct pirq *pirq;
 
     machine_gsi = pt_irq_bind->machine_irq;
     device = pt_irq_bind->u.pci.device;
@@ -327,14 +350,14 @@
         }
     }
 
-    pirq = pirq_info(d, machine_gsi);
-    pirq_dpci = pirq_dpci(pirq);
-
     /* clear the mirq info */
-    if ( pirq_dpci && (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
+    if ( test_bit(machine_gsi, hvm_irq_dpci->mapping))
     {
-        list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
+        list_for_each_safe ( digl_list, tmp,
+                &hvm_irq_dpci->mirq[machine_gsi].digl_list )
         {
+            digl = list_entry(digl_list,
+                    struct dev_intx_gsi_link, list);
             if ( digl->device == device &&
                  digl->intx   == intx &&
                  digl->link   == link &&
@@ -345,15 +368,15 @@
             }
         }
 
-        if ( list_empty(&pirq_dpci->digl_list) )
+        if ( list_empty(&hvm_irq_dpci->mirq[machine_gsi].digl_list) )
         {
-            pirq_guest_unbind(d, machine_gsi, pirq);
-            msixtbl_pt_unregister(d, pirq);
-            if ( pt_irq_need_timer(pirq_dpci->flags) )
-                kill_timer(&pirq_dpci->timer);
-            pirq_dpci->dom   = NULL;
-            pirq_dpci->flags = 0;
-            pirq_cleanup_check(pirq, d, machine_gsi);
+            pirq_guest_unbind(d, machine_gsi);
+            msixtbl_pt_unregister(d, machine_gsi);
+            if ( pt_irq_need_timer(hvm_irq_dpci->mirq[machine_gsi].flags) )
+                kill_timer(&hvm_irq_dpci->hvm_timer[machine_gsi]);
+            hvm_irq_dpci->mirq[machine_gsi].dom   = NULL;
+            hvm_irq_dpci->mirq[machine_gsi].flags = 0;
+            clear_bit(machine_gsi, hvm_irq_dpci->mapping);
         }
     }
     spin_unlock(&d->event_lock);
@@ -366,156 +389,120 @@
     return 0;
 }
 
-void pt_pirq_init(struct domain *d, struct hvm_pirq_dpci *dpci)
-{
-    INIT_LIST_HEAD(&dpci->digl_list);
-    dpci->gmsi.dest_vcpu_id = -1;
-}
-
-bool_t pt_pirq_cleanup_check(struct hvm_pirq_dpci *dpci)
-{
-    return !dpci->flags;
-}
-
-int pt_pirq_iterate(struct domain *d,
-                    int (*cb)(struct domain *, unsigned int,
-                              struct hvm_pirq_dpci *, void *),
-                    void *arg)
-{
-    int rc = 0;
-    unsigned int pirq = 0, n, i;
-    unsigned long indexes[8];
-    struct pirq *pirqs[ARRAY_SIZE(indexes)];
-
-    ASSERT(spin_is_locked(&d->event_lock));
-
-    do {
-        n = radix_tree_gang_lookup(&d->pirq_tree, (void **)pirqs, pirq,
-                                   ARRAY_SIZE(pirqs), indexes);
-        for ( i = 0; i < n; ++i )
-        {
-            struct hvm_pirq_dpci *pirq_dpci = pirq_dpci(pirqs[i]);
-
-            pirq = indexes[i];
-            if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
-                rc = cb(d, pirq, pirq_dpci, arg);
-        }
-    } while ( !rc && ++pirq < d->nr_pirqs && n == ARRAY_SIZE(pirqs) );
-
-    return rc;
-}
-
-int hvm_do_IRQ_dpci(struct domain *d, struct pirq *pirq)
+int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
 {
     struct hvm_irq_dpci *dpci = domain_get_irq_dpci(d);
-    struct hvm_pirq_dpci *pirq_dpci = pirq_dpci(pirq);
 
-    if ( !iommu_enabled || !dpci || !pirq_dpci ||
-         !(pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
+    ASSERT(spin_is_locked(&irq_desc[domain_pirq_to_irq(d, mirq)].lock));
+    if ( !iommu_enabled || !dpci || !test_bit(mirq, dpci->mapping))
         return 0;
 
-    pirq_dpci->masked = 1;
+    set_bit(mirq, dpci->dirq_mask);
     tasklet_schedule(&dpci->dirq_tasklet);
     return 1;
 }
 
 #ifdef SUPPORT_MSI_REMAPPING
 /* called with d->event_lock held */
-static void __msi_pirq_eoi(struct domain *d, struct hvm_pirq_dpci *pirq_dpci)
+static void __msi_pirq_eoi(struct domain *d, int pirq)
 {
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     irq_desc_t *desc;
 
-    if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) &&
-         (pirq_dpci->flags & HVM_IRQ_DPCI_MACH_MSI) )
+    if ( ( pirq >= 0 ) && ( pirq < d->nr_pirqs ) &&
+         test_bit(pirq, hvm_irq_dpci->mapping) &&
+         ( hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MACH_MSI) )
     {
-        struct pirq *pirq = dpci_pirq(pirq_dpci);
-
          BUG_ON(!local_irq_is_enabled());
-         desc = pirq_spin_lock_irq_desc(d, pirq, NULL);
+         desc = domain_spin_lock_irq_desc(d, pirq, NULL);
          if ( !desc )
             return;
 
          desc->status &= ~IRQ_INPROGRESS;
-         desc_guest_eoi(d, desc, pirq);
+         spin_unlock_irq(&desc->lock);
+
+         pirq_guest_eoi(d, pirq);
     }
 }
 
-static int _hvm_dpci_msi_eoi(struct domain *d, unsigned int pirq,
-                             struct hvm_pirq_dpci *pirq_dpci, void *arg)
-{
-    int vector = (long)arg;
-
-    if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MACH_MSI) &&
-         (pirq_dpci->gmsi.gvec == vector) )
-    {
-        int dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;
-        int dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);
-
-        if ( vlapic_match_dest(vcpu_vlapic(current), NULL, 0, dest,
-                               dest_mode) )
-        {
-            __msi_pirq_eoi(d, pirq_dpci);
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
 void hvm_dpci_msi_eoi(struct domain *d, int vector)
 {
-    if ( !iommu_enabled || !d->arch.hvm_domain.irq.dpci )
+    int pirq, dest, dest_mode;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+
+    if ( !iommu_enabled || (hvm_irq_dpci == NULL) )
        return;
 
     spin_lock(&d->event_lock);
-    pt_pirq_iterate(d, _hvm_dpci_msi_eoi, (void *)(long)vector);
+    for ( pirq = find_first_bit(hvm_irq_dpci->mapping, d->nr_pirqs);
+          pirq < d->nr_pirqs;
+          pirq = find_next_bit(hvm_irq_dpci->mapping, d->nr_pirqs, pirq + 1) )
+    {
+        if ( (!(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MACH_MSI)) ||
+                (hvm_irq_dpci->mirq[pirq].gmsi.gvec != vector) )
+            continue;
+
+        dest = hvm_irq_dpci->mirq[pirq].gmsi.gflags & VMSI_DEST_ID_MASK;
+        dest_mode = !!(hvm_irq_dpci->mirq[pirq].gmsi.gflags & VMSI_DM_MASK);
+        if ( vlapic_match_dest(vcpu_vlapic(current), NULL, 0, dest, dest_mode) 
)
+            break;
+    }
+    if ( pirq < d->nr_pirqs )
+        __msi_pirq_eoi(d, pirq);
     spin_unlock(&d->event_lock);
 }
 
-static int hvm_pci_msi_assert(struct domain *d,
-                              struct hvm_pirq_dpci *pirq_dpci)
+extern int vmsi_deliver(struct domain *d, int pirq);
+static int hvm_pci_msi_assert(struct domain *d, int pirq)
 {
-    struct pirq *pirq = dpci_pirq(pirq_dpci);
-
     if ( hvm_domain_use_pirq(d, pirq) )
         return send_guest_pirq(d, pirq);
     else
-        return vmsi_deliver(d, pirq_dpci);
+        return vmsi_deliver(d, pirq);
 }
 #endif
 
-static int _hvm_dirq_assist(struct domain *d, unsigned int pirq,
-                            struct hvm_pirq_dpci *pirq_dpci, void *arg)
+static void hvm_dirq_assist(unsigned long _d)
 {
+    unsigned int pirq;
     uint32_t device, intx;
+    struct domain *d = (struct domain *)_d;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     struct dev_intx_gsi_link *digl;
 
-    if ( test_and_clear_bool(pirq_dpci->masked) )
+    ASSERT(hvm_irq_dpci);
+
+    for ( pirq = find_first_bit(hvm_irq_dpci->dirq_mask, d->nr_pirqs);
+          pirq < d->nr_pirqs;
+          pirq = find_next_bit(hvm_irq_dpci->dirq_mask, d->nr_pirqs, pirq + 1) 
)
     {
+        if ( !test_and_clear_bit(pirq, hvm_irq_dpci->dirq_mask) )
+            continue;
+
+        spin_lock(&d->event_lock);
 #ifdef SUPPORT_MSI_REMAPPING
-        if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )
+        if ( hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_GUEST_MSI )
         {
-            hvm_pci_msi_assert(d, pirq_dpci);
-            return 0;
+            hvm_pci_msi_assert(d, pirq);
+            spin_unlock(&d->event_lock);
+            continue;
         }
 #endif
-        list_for_each_entry ( digl, &pirq_dpci->digl_list, list )
+        list_for_each_entry ( digl, &hvm_irq_dpci->mirq[pirq].digl_list, list )
         {
-            struct pirq *info = dpci_pirq(pirq_dpci);
-
             device = digl->device;
             intx = digl->intx;
-            if ( hvm_domain_use_pirq(d, info) )
-                send_guest_pirq(d, info);
+            if ( hvm_domain_use_pirq(d, pirq) )
+                send_guest_pirq(d, pirq);
             else
                 hvm_pci_intx_assert(d, device, intx);
-            pirq_dpci->pending++;
+            hvm_irq_dpci->mirq[pirq].pending++;
 
 #ifdef SUPPORT_MSI_REMAPPING
-            if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE )
+            if ( hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_TRANSLATE )
             {
                 /* for translated MSI to INTx interrupt, eoi as early as 
possible */
-                __msi_pirq_eoi(d, pirq_dpci);
+                __msi_pirq_eoi(d, pirq);
             }
 #endif
         }
@@ -527,50 +514,37 @@
          * guest will never deal with the irq, then the physical interrupt line
          * will never be deasserted.
          */
-        if ( pt_irq_need_timer(pirq_dpci->flags) )
-            set_timer(&pirq_dpci->timer, NOW() + PT_IRQ_TIME_OUT);
+        if ( pt_irq_need_timer(hvm_irq_dpci->mirq[pirq].flags) )
+            set_timer(&hvm_irq_dpci->hvm_timer[pirq],
+                      NOW() + PT_IRQ_TIME_OUT);
+        spin_unlock(&d->event_lock);
     }
-
-    return 0;
-}
-
-static void hvm_dirq_assist(unsigned long _d)
-{
-    struct domain *d = (struct domain *)_d;
-
-    ASSERT(d->arch.hvm_domain.irq.dpci);
-
-    spin_lock(&d->event_lock);
-    pt_pirq_iterate(d, _hvm_dirq_assist, NULL);
-    spin_unlock(&d->event_lock);
 }
 
 static void __hvm_dpci_eoi(struct domain *d,
+                           struct hvm_irq_dpci *hvm_irq_dpci,
                            struct hvm_girq_dpci_mapping *girq,
                            union vioapic_redir_entry *ent)
 {
-    uint32_t device, intx;
-    struct pirq *pirq;
-    struct hvm_pirq_dpci *pirq_dpci;
+    uint32_t device, intx, machine_gsi;
 
     device = girq->device;
     intx = girq->intx;
     hvm_pci_intx_deassert(d, device, intx);
 
-    pirq = pirq_info(d, girq->machine_gsi);
-    pirq_dpci = pirq_dpci(pirq);
+    machine_gsi = girq->machine_gsi;
 
     /*
      * No need to get vector lock for timer
      * since interrupt is still not EOIed
      */
-    if ( --pirq_dpci->pending ||
+    if ( --hvm_irq_dpci->mirq[machine_gsi].pending ||
          ( ent && ent->fields.mask ) ||
-         ! pt_irq_need_timer(pirq_dpci->flags) )
+         ! pt_irq_need_timer(hvm_irq_dpci->mirq[machine_gsi].flags) )
         return;
 
-    stop_timer(&pirq_dpci->timer);
-    pirq_guest_eoi(d, pirq);
+    stop_timer(&hvm_irq_dpci->hvm_timer[machine_gsi]);
+    pirq_guest_eoi(d, machine_gsi);
 }
 
 void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
@@ -595,7 +569,7 @@
         goto unlock;
 
     list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list )
-        __hvm_dpci_eoi(d, girq, ent);
+        __hvm_dpci_eoi(d, hvm_irq_dpci, girq, ent);
 
 unlock:
     spin_unlock(&d->event_lock);
diff -r 24346f749826 -r 10f27b8b3d63 xen/drivers/passthrough/pci.c
--- a/xen/drivers/passthrough/pci.c     Sun May 01 13:17:44 2011 +0100
+++ b/xen/drivers/passthrough/pci.c     Mon May 02 12:00:40 2011 +0100
@@ -236,28 +236,12 @@
     return ret;
 }
 
-static int pci_clean_dpci_irq(struct domain *d, unsigned int pirq,
-                              struct hvm_pirq_dpci *pirq_dpci, void *arg)
-{
-    struct dev_intx_gsi_link *digl, *tmp;
-
-    pirq_guest_unbind(d, pirq, dpci_pirq(pirq_dpci));
-
-    if ( pt_irq_need_timer(pirq_dpci->flags) )
-        kill_timer(&pirq_dpci->timer);
-
-    list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
-    {
-        list_del(&digl->list);
-        xfree(digl);
-    }
-
-    return 0;
-}
-
 static void pci_clean_dpci_irqs(struct domain *d)
 {
     struct hvm_irq_dpci *hvm_irq_dpci = NULL;
+    uint32_t i;
+    struct list_head *digl_list, *tmp;
+    struct dev_intx_gsi_link *digl;
 
     if ( !iommu_enabled )
         return;
@@ -271,7 +255,24 @@
     {
         tasklet_kill(&hvm_irq_dpci->dirq_tasklet);
 
-        pt_pirq_iterate(d, pci_clean_dpci_irq, NULL);
+        for ( i = find_first_bit(hvm_irq_dpci->mapping, d->nr_pirqs);
+              i < d->nr_pirqs;
+              i = find_next_bit(hvm_irq_dpci->mapping, d->nr_pirqs, i + 1) )
+        {
+            pirq_guest_unbind(d, i);
+
+            if ( pt_irq_need_timer(hvm_irq_dpci->mirq[i].flags) )
+                kill_timer(&hvm_irq_dpci->hvm_timer[i]);
+
+            list_for_each_safe ( digl_list, tmp,
+                                 &hvm_irq_dpci->mirq[i].digl_list )
+            {
+                digl = list_entry(digl_list,
+                                  struct dev_intx_gsi_link, list);
+                list_del(&digl->list);
+                xfree(digl);
+            }
+        }
 
         d->arch.hvm_domain.irq.dpci = NULL;
         free_hvm_irq_dpci(hvm_irq_dpci);
diff -r 24346f749826 -r 10f27b8b3d63 xen/drivers/passthrough/vtd/x86/vtd.c
--- a/xen/drivers/passthrough/vtd/x86/vtd.c     Sun May 01 13:17:44 2011 +0100
+++ b/xen/drivers/passthrough/vtd/x86/vtd.c     Mon May 02 12:00:40 2011 +0100
@@ -68,32 +68,12 @@
     return (void *)fix_to_virt(FIX_IOMMU_REGS_BASE_0 + nr_iommus);
 }
 
-static int _hvm_dpci_isairq_eoi(struct domain *d, unsigned int pirq,
-                                struct hvm_pirq_dpci *pirq_dpci, void *arg)
+void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq)
 {
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
-    unsigned int isairq = (long)arg;
+    struct hvm_irq_dpci *dpci = NULL;
     struct dev_intx_gsi_link *digl, *tmp;
-
-    list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )
-    {
-        if ( hvm_irq->pci_link.route[digl->link] == isairq )
-        {
-            hvm_pci_intx_deassert(d, digl->device, digl->intx);
-            if ( --pirq_dpci->pending == 0 )
-            {
-                stop_timer(&pirq_dpci->timer);
-                pirq_guest_eoi(d, dpci_pirq(pirq_dpci));
-            }
-        }
-    }
-
-    return 0;
-}
-
-void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq)
-{
-    struct hvm_irq_dpci *dpci = NULL;
+    int i;
 
     ASSERT(isairq < NR_ISAIRQS);
     if ( !iommu_enabled)
@@ -103,10 +83,29 @@
 
     dpci = domain_get_irq_dpci(d);
 
-    if ( dpci && test_bit(isairq, dpci->isairq_map) )
+    if ( !dpci || !test_bit(isairq, dpci->isairq_map) )
     {
-        /* Multiple mirq may be mapped to one isa irq */
-        pt_pirq_iterate(d, _hvm_dpci_isairq_eoi, (void *)(long)isairq);
+        spin_unlock(&d->event_lock);
+        return;
+    }
+    /* Multiple mirq may be mapped to one isa irq */
+    for ( i = find_first_bit(dpci->mapping, d->nr_pirqs);
+          i < d->nr_pirqs;
+          i = find_next_bit(dpci->mapping, d->nr_pirqs, i + 1) )
+    {
+        list_for_each_entry_safe ( digl, tmp,
+            &dpci->mirq[i].digl_list, list )
+        {
+            if ( hvm_irq->pci_link.route[digl->link] == isairq )
+            {
+                hvm_pci_intx_deassert(d, digl->device, digl->intx);
+                if ( --dpci->mirq[i].pending == 0 )
+                {
+                    stop_timer(&dpci->hvm_timer[i]);
+                    pirq_guest_eoi(d, i);
+                }
+            }
+        }
     }
     spin_unlock(&d->event_lock);
 }
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h     Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/asm-ia64/domain.h     Mon May 02 12:00:40 2011 +0100
@@ -11,7 +11,6 @@
 #include <xen/list.h>
 #include <xen/cpumask.h>
 #include <xen/mm.h>
-#include <xen/hvm/irq.h>
 #include <asm/fpswa.h>
 #include <xen/rangeset.h>
 
@@ -317,23 +316,6 @@
     cpumask_t cache_coherent_map;
 };
 
-struct arch_pirq {
-    struct hvm_pirq_dpci dpci;
-};
-
-#define pirq_dpci(pirq) ((pirq) ? &(pirq)->arch.dpci : NULL)
-#define dpci_pirq(dpci) container_of(dpci, struct pirq, arch.dpci)
-
-#define alloc_pirq_struct(d) ({ \
-    struct pirq *pirq = xmalloc(struct pirq); \
-    if ( pirq ) \
-    { \
-        memset(pirq, 0, sizeof(*pirq)); \
-        pt_pirq_init(d, &pirq->arch.dpci); \
-    } \
-    pirq; \
-})
-
 #include <asm/uaccess.h> /* for KERNEL_DS */
 #include <asm/pgtable.h>
 
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/asm-x86/domain.h      Mon May 02 12:00:40 2011 +0100
@@ -3,7 +3,6 @@
 
 #include <xen/config.h>
 #include <xen/mm.h>
-#include <xen/radix-tree.h>
 #include <asm/hvm/vcpu.h>
 #include <asm/hvm/domain.h>
 #include <asm/e820.h>
@@ -285,7 +284,11 @@
     const char *nested_p2m_function;
 
     /* NB. protected by d->event_lock and by irq_desc[irq].lock */
-    struct radix_tree_root irq_pirq;
+    int *irq_pirq;
+    int *pirq_irq;
+    /* pirq to emulated irq and vice versa */
+    int *emuirq_pirq;
+    int *pirq_emuirq;
 
     /* Maximum physical-address bitwidth supported by this guest. */
     unsigned int physaddr_bitsize;
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h  Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/asm-x86/hvm/domain.h  Mon May 02 12:00:40 2011 +0100
@@ -59,9 +59,6 @@
     /* VCPU which is current target for 8259 interrupts. */
     struct vcpu           *i8259_target;
 
-    /* emulated irq to pirq */
-    struct radix_tree_root emuirq_pirq;
-
     /* hvm_print_line() logging. */
 #define HVM_PBUF_SIZE 80
     char                  *pbuf;
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h     Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/asm-x86/hvm/irq.h     Mon May 02 12:00:40 2011 +0100
@@ -111,6 +111,4 @@
  */
 #define SUPPORT_MSI_REMAPPING 1
 
-void msixtbl_pt_cleanup(struct domain *d);
-
 #endif /* __ASM_X86_HVM_IRQ_H__ */
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/asm-x86/irq.h Mon May 02 12:00:40 2011 +0100
@@ -7,7 +7,6 @@
 #include <asm/atomic.h>
 #include <xen/cpumask.h>
 #include <xen/smp.h>
-#include <xen/hvm/irq.h>
 #include <irq_vectors.h>
 #include <asm/percpu.h>
 
@@ -106,20 +105,6 @@
 
 DECLARE_PER_CPU(unsigned int, irq_count);
 
-struct pirq;
-struct arch_pirq {
-    int irq;
-    union {
-        struct hvm_pirq {
-            int emuirq;
-            struct hvm_pirq_dpci dpci;
-        } hvm;
-    };
-};
-
-#define pirq_dpci(pirq) ((pirq) ? &(pirq)->arch.hvm.dpci : NULL)
-#define dpci_pirq(pd) container_of(pd, struct pirq, arch.hvm.dpci)
-
 int pirq_shared(struct domain *d , int irq);
 
 int map_domain_pirq(struct domain *d, int pirq, int irq, int type,
@@ -129,7 +114,7 @@
 void free_domain_pirqs(struct domain *d);
 int map_domain_emuirq_pirq(struct domain *d, int pirq, int irq);
 int unmap_domain_pirq_emuirq(struct domain *d, int pirq);
-bool_t hvm_domain_use_pirq(const struct domain *, const struct pirq *);
+int hvm_domain_use_pirq(struct domain *d, int irq);
 
 int  init_irq_data(void);
 
@@ -158,17 +143,11 @@
 
 void irq_set_affinity(struct irq_desc *, const cpumask_t *mask);
 
-int init_domain_irq_mapping(struct domain *);
-void cleanup_domain_irq_mapping(struct domain *);
-
-#define domain_pirq_to_irq(d, pirq) pirq_field(d, pirq, arch.irq)
-#define domain_irq_to_pirq(d, irq) \
-    ((long)radix_tree_lookup(&(d)->arch.irq_pirq, irq))
+#define domain_pirq_to_irq(d, pirq) ((d)->arch.pirq_irq[pirq])
+#define domain_irq_to_pirq(d, irq) ((d)->arch.irq_pirq[irq])
 #define PIRQ_ALLOCATED -1
-#define domain_pirq_to_emuirq(d, pirq) pirq_field(d, pirq, arch.hvm.emuirq)
-#define domain_emuirq_to_pirq(d, emuirq) \
-    (((long)radix_tree_lookup(&(d)->arch.hvm_domain.emuirq_pirq, emuirq) ?: \
-     IRQ_UNBOUND + 1) - 1)
+#define domain_pirq_to_emuirq(d, pirq) ((d)->arch.pirq_emuirq[pirq])
+#define domain_emuirq_to_pirq(d, emuirq) ((d)->arch.emuirq_pirq[emuirq])
 #define IRQ_UNBOUND -1
 #define IRQ_PT -2
 
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/xen/domain.h
--- a/xen/include/xen/domain.h  Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/xen/domain.h  Mon May 02 12:00:40 2011 +0100
@@ -38,12 +38,6 @@
 void free_vcpu_guest_context(struct vcpu_guest_context *);
 #endif
 
-/* Allocate/free a PIRQ structure. */
-#ifndef alloc_pirq_struct
-struct pirq *alloc_pirq_struct(struct domain *);
-#endif
-#define free_pirq_struct xfree
-
 /*
  * Initialise/destroy arch-specific details of a VCPU.
  *  - vcpu_initialise() is called after the basic generic fields of the
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/xen/event.h
--- a/xen/include/xen/event.h   Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/xen/event.h   Mon May 02 12:00:40 2011 +0100
@@ -36,7 +36,7 @@
  *  @pirq:     Physical IRQ number
  * Returns TRUE if the delivery port was already pending.
  */
-int send_guest_pirq(struct domain *, const struct pirq *);
+int send_guest_pirq(struct domain *d, int pirq);
 
 /* Send a notification from a given domain's event-channel port. */
 int evtchn_send(struct domain *d, unsigned int lport);
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/xen/hvm/irq.h
--- a/xen/include/xen/hvm/irq.h Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/xen/hvm/irq.h Mon May 02 12:00:40 2011 +0100
@@ -25,7 +25,7 @@
 #include <xen/types.h>
 #include <xen/spinlock.h>
 #include <xen/tasklet.h>
-#include <xen/timer.h>
+#include <asm/irq.h>
 #include <public/hvm/save.h>
 
 struct dev_intx_gsi_link {
@@ -38,15 +38,11 @@
 
 #define _HVM_IRQ_DPCI_MACH_PCI_SHIFT            0
 #define _HVM_IRQ_DPCI_MACH_MSI_SHIFT            1
-#define _HVM_IRQ_DPCI_MAPPED_SHIFT              2
-#define _HVM_IRQ_DPCI_EOI_LATCH_SHIFT           3
 #define _HVM_IRQ_DPCI_GUEST_PCI_SHIFT           4
 #define _HVM_IRQ_DPCI_GUEST_MSI_SHIFT           5
 #define _HVM_IRQ_DPCI_TRANSLATE_SHIFT          15
 #define HVM_IRQ_DPCI_MACH_PCI        (1 << _HVM_IRQ_DPCI_MACH_PCI_SHIFT)
 #define HVM_IRQ_DPCI_MACH_MSI        (1 << _HVM_IRQ_DPCI_MACH_MSI_SHIFT)
-#define HVM_IRQ_DPCI_MAPPED          (1 << _HVM_IRQ_DPCI_MAPPED_SHIFT)
-#define HVM_IRQ_DPCI_EOI_LATCH       (1 << _HVM_IRQ_DPCI_EOI_LATCH_SHIFT)
 #define HVM_IRQ_DPCI_GUEST_PCI       (1 << _HVM_IRQ_DPCI_GUEST_PCI_SHIFT)
 #define HVM_IRQ_DPCI_GUEST_MSI       (1 << _HVM_IRQ_DPCI_GUEST_MSI_SHIFT)
 #define HVM_IRQ_DPCI_TRANSLATE       (1 << _HVM_IRQ_DPCI_TRANSLATE_SHIFT)
@@ -67,6 +63,14 @@
     int dest_vcpu_id; /* -1 :multi-dest, non-negative: dest_vcpu_id */
 };
 
+struct hvm_mirq_dpci_mapping {
+    uint32_t flags;
+    int pending;
+    struct list_head digl_list;
+    struct domain *dom;
+    struct hvm_gmsi_info gmsi;
+};
+
 struct hvm_girq_dpci_mapping {
     struct list_head list;
     uint8_t device;
@@ -84,33 +88,20 @@
 
 /* Protected by domain's event_lock */
 struct hvm_irq_dpci {
+    /* Machine IRQ to guest device/intx mapping. */
+    unsigned long *mapping;
+    struct hvm_mirq_dpci_mapping *mirq;
+    unsigned long *dirq_mask;
     /* Guest IRQ to guest device/intx mapping. */
     struct list_head girq[NR_HVM_IRQS];
     /* Record of mapped ISA IRQs */
     DECLARE_BITMAP(isairq_map, NR_ISAIRQS);
     /* Record of mapped Links */
     uint8_t link_cnt[NR_LINK];
+    struct timer *hvm_timer;
     struct tasklet dirq_tasklet;
 };
 
-/* Machine IRQ to guest device/intx mapping. */
-struct hvm_pirq_dpci {
-    uint32_t flags;
-    bool_t masked;
-    uint16_t pending;
-    struct list_head digl_list;
-    struct domain *dom;
-    struct hvm_gmsi_info gmsi;
-    struct timer timer;
-};
-
-void pt_pirq_init(struct domain *, struct hvm_pirq_dpci *);
-bool_t pt_pirq_cleanup_check(struct hvm_pirq_dpci *);
-int pt_pirq_iterate(struct domain *d,
-                    int (*cb)(struct domain *, unsigned int pirq,
-                              struct hvm_pirq_dpci *, void *arg),
-                    void *arg);
-
 /* Modify state of a PCI INTx wire. */
 void hvm_pci_intx_assert(
     struct domain *d, unsigned int device, unsigned int intx);
@@ -129,6 +120,4 @@
 void hvm_assert_evtchn_irq(struct vcpu *v);
 void hvm_set_callback_via(struct domain *d, uint64_t via);
 
-int vmsi_deliver(struct domain *, const struct hvm_pirq_dpci *);
-
 #endif /* __XEN_HVM_IRQ_H__ */
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/xen/iommu.h
--- a/xen/include/xen/iommu.h   Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/xen/iommu.h   Mon May 02 12:00:40 2011 +0100
@@ -88,9 +88,7 @@
 void iommu_pte_flush(struct domain *d, u64 gfn, u64 *pte, int order, int 
present);
 void iommu_set_pgd(struct domain *d);
 void iommu_domain_teardown(struct domain *d);
-
-struct pirq;
-int hvm_do_IRQ_dpci(struct domain *, struct pirq *);
+int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq);
 int dpci_ioport_intercept(ioreq_t *p);
 int pt_irq_create_bind_vtd(struct domain *d,
                            xen_domctl_bind_pt_irq_t *pt_irq_bind);
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/xen/irq.h
--- a/xen/include/xen/irq.h     Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/xen/irq.h     Mon May 02 12:00:40 2011 +0100
@@ -135,41 +135,13 @@
 
 struct domain;
 struct vcpu;
-
-struct pirq {
-    u16 evtchn;
-    bool_t masked;
-    struct arch_pirq arch;
-};
-
-#define pirq_info(d, p) ((struct pirq *)radix_tree_lookup(&(d)->pirq_tree, p))
-
-/* Use this instead of pirq_info() if the structure may need allocating. */
-extern struct pirq *pirq_get_info(struct domain *, int pirq);
-
-#define pirq_field(d, p, f) ({ \
-    const struct pirq *__pi = pirq_info(d, p); \
-    __pi ? __pi->f : 0; \
-})
-#define pirq_to_evtchn(d, pirq) pirq_field(d, pirq, evtchn)
-#define pirq_masked(d, pirq) pirq_field(d, pirq, masked)
-
-void pirq_cleanup_check(struct pirq *, struct domain *, int);
-
-#define pirq_cleanup_check(info, d, pirq) \
-    ((info)->evtchn ? pirq_cleanup_check(info, d, pirq) : (void)0)
-
-extern void pirq_guest_eoi(struct domain *, struct pirq *);
-extern void desc_guest_eoi(struct domain *, struct irq_desc *, struct pirq *);
+extern int pirq_guest_eoi(struct domain *d, int irq);
 extern int pirq_guest_unmask(struct domain *d);
-extern int pirq_guest_bind(struct vcpu *, int pirq, struct pirq *,
-    int will_share);
-extern void pirq_guest_unbind(struct domain *d, int pirq, struct pirq *);
+extern int pirq_guest_bind(struct vcpu *v, int irq, int will_share);
+extern void pirq_guest_unbind(struct domain *d, int irq);
 extern void pirq_set_affinity(struct domain *d, int irq, const cpumask_t *);
 extern irq_desc_t *domain_spin_lock_irq_desc(
     struct domain *d, int irq, unsigned long *pflags);
-extern irq_desc_t *pirq_spin_lock_irq_desc(
-    struct domain *, const struct pirq *, unsigned long *pflags);
 
 static inline void set_native_irq_info(unsigned int irq, const cpumask_t *mask)
 {
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/xen/pci.h
--- a/xen/include/xen/pci.h     Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/xen/pci.h     Mon May 02 12:00:40 2011 +0100
@@ -117,9 +117,8 @@
 int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap);
 int pci_find_ext_capability(int seg, int bus, int devfn, int cap);
 
-struct pirq;
-int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
-void msixtbl_pt_unregister(struct domain *, struct pirq *);
+int msixtbl_pt_register(struct domain *d, int pirq, uint64_t gtable);
+void msixtbl_pt_unregister(struct domain *d, int pirq);
 void pci_enable_acs(struct pci_dev *pdev);
 
 #endif /* __XEN_PCI_H__ */
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/xen/radix-tree.h
--- a/xen/include/xen/radix-tree.h      Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/xen/radix-tree.h      Mon May 02 12:00:40 2011 +0100
@@ -72,7 +72,7 @@
                         void(*node_free)(struct radix_tree_node *));
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
-                       unsigned long first_index, unsigned int max_items,
-                       unsigned long *indexes);
+                       unsigned long first_index, unsigned int max_items);
+void radix_tree_init(void);
 
 #endif /* _XEN_RADIX_TREE_H */
diff -r 24346f749826 -r 10f27b8b3d63 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Sun May 01 13:17:44 2011 +0100
+++ b/xen/include/xen/sched.h   Mon May 02 12:00:40 2011 +0100
@@ -21,7 +21,6 @@
 #include <xen/irq.h>
 #include <xen/mm.h>
 #include <xen/tasklet.h>
-#include <xen/radix-tree.h>
 #include <public/mem_event.h>
 #include <xen/cpumask.h>
 #include <xen/nodemask.h>
@@ -235,11 +234,13 @@
     struct grant_table *grant_table;
 
     /*
-     * Interrupt to event-channel mappings and other per-guest-pirq data.
-     * Protected by the domain's event-channel spinlock.
+     * Interrupt to event-channel mappings. Updates should be protected by the 
+     * domain's event-channel spinlock. Read accesses can also synchronise on 
+     * the lock, but races don't usually matter.
      */
     unsigned int     nr_pirqs;
-    struct radix_tree_root pirq_tree;
+    u16             *pirq_to_evtchn;
+    unsigned long   *pirq_mask;
 
     /* I/O capabilities (access to IRQs and memory-mapped I/O). */
     struct rangeset *iomem_caps;

_______________________________________________
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] Revert 23295:4891f1f41ba5 and 23296:24346f749826, Xen patchbot-unstable <=