vt-d: Free memory of g2m_ioport_list.
authorKeir Fraser <keir@xensource.com>
Tue, 6 Nov 2007 09:43:22 +0000 (09:43 +0000)
committerKeir Fraser <keir@xensource.com>
Tue, 6 Nov 2007 09:43:22 +0000 (09:43 +0000)
This patch frees memory of g2m_ioport_list when remove g2m_ioport or
destroy iommu domain to avoid memory leak. In addtion, does some
cleanup on domctl.c.

Signed-off-by: Weidong Han <weidong.han@intel.com>
xen/arch/x86/domctl.c
xen/arch/x86/hvm/vmx/vtd/io.c

index d79dc55059ebad050acab1e67c4e2f75042e63b2..9b2fcd12fddbe82131047600b136f8e4687fcbdb 100644 (file)
@@ -535,9 +535,10 @@ long arch_do_domctl(
         if ( !vtd_enabled )
             break;
 
-        if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) ) {
+        if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) )
+        {
             gdprintk(XENLOG_ERR,
-                "XEN_DOMCTL_assign_device: get_domain_by_id() failed\n"); 
+                "XEN_DOMCTL_assign_device: get_domain_by_id() failed\n");
             break;
         }
         hd = domain_hvm_iommu(d);
@@ -548,7 +549,7 @@ long arch_do_domctl(
             break;
 
         ret = assign_device(d, bus, devfn);
-        gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: bdf = %x:%x:%x\n",
+        gdprintk(XENLOG_INFO, "XEN_DOMCTL_assign_device: bdf = %x:%x:%x\n",
             bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
         put_domain(d);
     }
@@ -569,7 +570,7 @@ long arch_do_domctl(
             gdprintk(XENLOG_ERR, "pt_irq_create_bind failed!\n");
         rcu_unlock_domain(d);
     }
-    break;    
+    break;
 
     case XEN_DOMCTL_memory_mapping:
     {
@@ -587,25 +588,25 @@ long arch_do_domctl(
         if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) )
             break;
 
-        ret=0;        
-        if ( domctl->u.memory_mapping.add_mapping ) 
+        ret=0;
+        if ( domctl->u.memory_mapping.add_mapping )
         {
             gdprintk(XENLOG_INFO,
                 "memory_map:add: gfn=%lx mfn=%lx nr_mfns=%lx\n",
-                gfn, mfn, nr_mfns);   
-            
+                gfn, mfn, nr_mfns);
+
             ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
             for ( i = 0; i < nr_mfns; i++ )
-                set_mmio_p2m_entry(d, gfn+i, _mfn(mfn+i)); 
+                set_mmio_p2m_entry(d, gfn+i, _mfn(mfn+i));
         }
-        else 
+        else
         {
             gdprintk(XENLOG_INFO,
                 "memory_map:remove: gfn=%lx mfn=%lx nr_mfns=%lx\n",
                  gfn, mfn, nr_mfns);
 
             for ( i = 0; i < nr_mfns; i++ )
-                clear_mmio_p2m_entry(d, gfn+i); 
+                clear_mmio_p2m_entry(d, gfn+i);
             ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
         }
 
@@ -644,39 +645,42 @@ long arch_do_domctl(
             gdprintk(XENLOG_INFO,
                 "ioport_map:add f_gport=%x f_mport=%x np=%x\n",
                 fgp, fmp, np);
-                
+
             list_for_each_entry(g2m_ioport, &hd->g2m_ioport_list, list)
-                if (g2m_ioport->mport == fmp ) {
+                if (g2m_ioport->mport == fmp )
+                {
                     g2m_ioport->gport = fgp;
-                    g2m_ioport->np = np;                    
+                    g2m_ioport->np = np;
                     found = 1;
                     break;
                 }
-            if ( !found ) 
-            {                 
+            if ( !found )
+            {
                 g2m_ioport = xmalloc(struct g2m_ioport);
                 g2m_ioport->gport = fgp;
                 g2m_ioport->mport = fmp;
                 g2m_ioport->np = np;
                 list_add_tail(&g2m_ioport->list, &hd->g2m_ioport_list);
-            } 
+            }
             ret = ioports_permit_access(d, fmp, fmp + np - 1);
-            
         }
-        else {
+        else
+        {
             gdprintk(XENLOG_INFO,
                 "ioport_map:remove f_gport=%x f_mport=%x np=%x\n",
                 fgp, fmp, np);
             list_for_each_entry(g2m_ioport, &hd->g2m_ioport_list, list)
-                if ( g2m_ioport->mport == fmp ) {
+                if ( g2m_ioport->mport == fmp )
+                {
                     list_del(&g2m_ioport->list);
+                    xfree(g2m_ioport);
                     break;
                 }
             ret = ioports_deny_access(d, fmp, fmp + np - 1);
         }
         rcu_unlock_domain(d);
     }
-    break;    
+    break;
 
     case XEN_DOMCTL_pin_mem_cacheattr:
     {
index 28d42a973a08066120acd45d439e8c4eb22484f9..336cee40de2f270540dcfe4d18f9ebc7bc2edac1 100644 (file)
@@ -164,6 +164,9 @@ void iommu_domain_destroy(struct domain *d)
 {
     struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     uint32_t i;
+    struct hvm_iommu *hd  = domain_hvm_iommu(d);
+    struct list_head *ioport_list, *tmp;
+    struct g2m_ioport *ioport;
 
     if ( !vtd_enabled )
         return;
@@ -180,5 +183,15 @@ void iommu_domain_destroy(struct domain *d)
         xfree(hvm_irq_dpci);
     }
 
+    if ( hd )
+    {
+        list_for_each_safe ( ioport_list, tmp, &hd->g2m_ioport_list )
+        {
+            ioport = list_entry(ioport_list, struct g2m_ioport, list);
+            list_del(&ioport->list);
+            xfree(ioport);
+        }
+    }
+
     iommu_domain_teardown(d);
 }