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

[Xen-changelog] [xen-unstable] VT-d: check return value of pirq_guest_bind()



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1228827329 0
# Node ID 043aba2b67a195d2c2707f8fd0c05bbbf2078d2a
# Parent  f7f8f44b9292a30707bd645739390ef3d0f22232
VT-d: check return value of pirq_guest_bind()

The eliminates a hypervisor crash when the respective domain dies or
gets the device hot removed.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Reviewed-by: Weidong Han <weidong.han@xxxxxxxxx>
---
 xen/drivers/passthrough/io.c |   35 +++++++++++++++++++++++++++++++----
 1 files changed, 31 insertions(+), 4 deletions(-)

diff -r f7f8f44b9292 -r 043aba2b67a1 xen/drivers/passthrough/io.c
--- a/xen/drivers/passthrough/io.c      Tue Dec 09 12:53:19 2008 +0000
+++ b/xen/drivers/passthrough/io.c      Tue Dec 09 12:55:29 2008 +0000
@@ -60,7 +60,7 @@ int pt_irq_create_bind_vtd(
     uint32_t machine_gsi, guest_gsi;
     uint32_t device, intx, link;
     struct dev_intx_gsi_link *digl;
-    int pirq = pt_irq_bind->machine_irq;
+    int rc, pirq = pt_irq_bind->machine_irq;
 
     if ( pirq < 0 || pirq >= NR_IRQS )
         return -EINVAL;
@@ -98,7 +98,17 @@ int pt_irq_create_bind_vtd(
             hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags;
             hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = pirq;
             /* bind after hvm_irq_dpci is setup to avoid race with irq 
handler*/
-            pirq_guest_bind(d->vcpu[0], pirq, 0);
+            rc = pirq_guest_bind(d->vcpu[0], pirq, 0);
+            if ( unlikely(rc) )
+            {
+                hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = 0;
+                hvm_irq_dpci->mirq[pirq].gmsi.gflags = 0;
+                hvm_irq_dpci->mirq[pirq].gmsi.gvec = 0;
+                clear_bit(_HVM_IRQ_DPCI_MSI, &hvm_irq_dpci->mirq[pirq].flags);
+                clear_bit(pirq, hvm_irq_dpci->mapping);
+                spin_unlock(&d->event_lock);
+                return rc;
+            }
         }
         else if (hvm_irq_dpci->mirq[pirq].gmsi.gvec != pt_irq_bind->u.msi.gvec
                 ||hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] != pirq)
@@ -139,13 +149,30 @@ int pt_irq_create_bind_vtd(
         /* Bind the same mirq once in the same domain */
         if ( !test_and_set_bit(machine_gsi, hvm_irq_dpci->mapping))
         {
+            unsigned int vector = domain_irq_to_vector(d, machine_gsi);
+
             hvm_irq_dpci->mirq[machine_gsi].dom = d;
 
             /* Init timer before binding */
-            init_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, 
machine_gsi)],
+            init_timer(&hvm_irq_dpci->hvm_timer[vector],
                        pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 0);
             /* Deal with gsi for legacy devices */
-            pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE);
+            rc = pirq_guest_bind(d->vcpu[0], machine_gsi, 
BIND_PIRQ__WILL_SHARE);
+            if ( unlikely(rc) )
+            {
+                kill_timer(&hvm_irq_dpci->hvm_timer[vector]);
+                hvm_irq_dpci->mirq[machine_gsi].dom = NULL;
+                clear_bit(machine_gsi, hvm_irq_dpci->mapping);
+                hvm_irq_dpci->girq[guest_gsi].machine_gsi = 0;
+                hvm_irq_dpci->girq[guest_gsi].intx = 0;
+                hvm_irq_dpci->girq[guest_gsi].device = 0;
+                hvm_irq_dpci->girq[guest_gsi].valid = 0;
+                list_del(&digl->list);
+                hvm_irq_dpci->link_cnt[link]--;
+                spin_unlock(&d->event_lock);
+                xfree(digl);
+                return rc;
+            }
         }
 
         gdprintk(XENLOG_INFO VTDPREFIX,

_______________________________________________
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®.