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

[Xen-devel] [PATCH 6 of 6] Enable ats devices on amd iommu systems



# HG changeset patch
# User Wei Wang <wei.wang2@xxxxxxx>
# Date 1319201424 -7200
# Node ID 1ccad89116b57c95c0ead34c9f8cc4b67fec9316
# Parent  6009089b0511c843f54435d02dcd72394d7e164f
Enable ats devices on amd iommu systems

Signed-off-by: Wei Wang <wei.wang2@xxxxxxx>

diff -r 6009089b0511 -r 1ccad89116b5 xen/drivers/passthrough/amd/iommu_map.c
--- a/xen/drivers/passthrough/amd/iommu_map.c   Fri Oct 21 14:50:23 2011 +0200
+++ b/xen/drivers/passthrough/amd/iommu_map.c   Fri Oct 21 14:50:24 2011 +0200
@@ -368,6 +368,17 @@ void amd_iommu_set_root_page_table(
     dte[0] = entry;
 }
 
+void iommu_dte_set_iotlb(u32 *dte, u8 i)
+{
+    u32 entry;
+
+    entry = dte[3];
+    set_field_in_reg_u32(!!i, entry,
+                         IOMMU_DEV_TABLE_IOTLB_SUPPORT_MASK,
+                         IOMMU_DEV_TABLE_IOTLB_SUPPORT_SHIFT, &entry);
+    dte[3] = entry;
+}
+
 void __init amd_iommu_set_intremap_table(
     u32 *dte, u64 intremap_ptr, u8 int_valid)
 {
diff -r 6009089b0511 -r 1ccad89116b5 xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c       Fri Oct 21 14:50:23 
2011 +0200
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c       Fri Oct 21 14:50:24 
2011 +0200
@@ -81,11 +81,12 @@ static void disable_translation(u32 *dte
 }
 
 static void amd_iommu_setup_domain_device(
-    struct domain *domain, struct amd_iommu *iommu, int bdf)
+    struct domain *domain, struct amd_iommu *iommu, u8 bus, u8 devfn)
 {
     void *dte;
     unsigned long flags;
     int req_id, valid = 1;
+    int dte_i = 0;
 
     struct hvm_iommu *hd = domain_hvm_iommu(domain);
 
@@ -94,8 +95,11 @@ static void amd_iommu_setup_domain_devic
     if ( iommu_passthrough && (domain->domain_id == 0) )
         valid = 0;
 
+    if ( ats_enabled )
+        dte_i = 1;
+
     /* get device-table entry */
-    req_id = get_dma_requestor_id(iommu->seg, bdf);
+    req_id = get_dma_requestor_id(iommu->seg, (bus << 8) | devfn);
     dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
 
     spin_lock_irqsave(&iommu->lock, flags);
@@ -107,6 +111,9 @@ static void amd_iommu_setup_domain_devic
             (u32 *)dte, page_to_maddr(hd->root_table), hd->domain_id,
             hd->paging_mode, valid);
 
+        if ( pci_ats_device(iommu->seg, bus, devfn) && iommu->iotlb_support )
+            iommu_dte_set_iotlb((u32 *)dte, dte_i);
+
         invalidate_dev_table_entry(iommu, req_id);
         flush_command_buffer(iommu);
 
@@ -118,6 +125,19 @@ static void amd_iommu_setup_domain_devic
     }
 
     spin_unlock_irqrestore(&iommu->lock, flags);
+
+    ASSERT(spin_is_locked(&pcidevs_lock));
+
+    if ( pci_ats_device(iommu->seg, bus, devfn) && ats_enabled &&
+         !pci_ats_enabled(iommu->seg, bus, devfn) )
+    {
+        struct pci_ats_dev* pdev;
+        enable_ats_device(iommu->seg, bus, devfn);
+        pdev = get_ats_device(iommu->seg, bus, devfn);
+
+        if ( pdev )
+            amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
+    }
 }
 
 static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev)
@@ -126,7 +146,8 @@ static void __init amd_iommu_setup_dom0_
     struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
 
     if ( likely(iommu != NULL) )
-        amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
+        amd_iommu_setup_domain_device(pdev->domain, iommu, pdev->bus, 
+                                      pdev->devfn);
     else
         AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n",
                         pdev->seg, pdev->bus,
@@ -261,21 +282,26 @@ static void __init amd_iommu_dom0_init(s
     setup_dom0_pci_devices(d, amd_iommu_setup_dom0_device);
 }
 
-static void amd_iommu_disable_domain_device(
-    struct domain *domain, struct amd_iommu *iommu, int bdf)
+void amd_iommu_disable_domain_device(struct domain *domain, 
+                                     struct amd_iommu *iommu, u8 bus, u8 devfn)
 {
     void *dte;
     unsigned long flags;
     int req_id;
 
     BUG_ON ( iommu->dev_table.buffer == NULL );
-    req_id = get_dma_requestor_id(iommu->seg, bdf);
+
+    req_id = get_dma_requestor_id(iommu->seg, (bus << 8) | devfn);
     dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
 
     spin_lock_irqsave(&iommu->lock, flags);
     if ( is_translation_valid((u32 *)dte) )
     {
         disable_translation((u32 *)dte);
+
+        if ( pci_ats_device(iommu->seg, bus, devfn) && iommu->iotlb_support )
+            iommu_dte_set_iotlb((u32 *)dte, 0);
+
         invalidate_dev_table_entry(iommu, req_id);
         flush_command_buffer(iommu);
         AMD_IOMMU_DEBUG("Disable: device id = 0x%04x, "
@@ -284,6 +310,12 @@ static void amd_iommu_disable_domain_dev
                         domain_hvm_iommu(domain)->paging_mode);
     }
     spin_unlock_irqrestore(&iommu->lock, flags);
+
+    ASSERT(spin_is_locked(&pcidevs_lock));
+
+    if ( pci_ats_device(iommu->seg, bus, devfn) && ats_enabled && 
+         pci_ats_enabled(iommu->seg, bus, devfn) )
+       disable_ats_device(iommu->seg, bus, devfn); 
 }
 
 static int reassign_device( struct domain *source, struct domain *target,
@@ -310,7 +342,7 @@ static int reassign_device( struct domai
         return -ENODEV;
     }
 
-    amd_iommu_disable_domain_device(source, iommu, bdf);
+    amd_iommu_disable_domain_device(source, iommu, bus, devfn);
 
     list_move(&pdev->domain_list, &target->arch.pdev_list);
     pdev->domain = target;
@@ -320,7 +352,7 @@ static int reassign_device( struct domai
     if ( t->root_table == NULL )
         allocate_domain_resources(t);
 
-    amd_iommu_setup_domain_device(target, iommu, bdf);
+    amd_iommu_setup_domain_device(target, iommu, bus, devfn);
     AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n",
                     seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
                     source->domain_id, target->domain_id);
@@ -432,7 +464,8 @@ static int amd_iommu_add_device(struct p
         return -ENODEV;
     }
 
-    amd_iommu_setup_domain_device(pdev->domain, iommu, bdf);
+    amd_iommu_setup_domain_device(pdev->domain, iommu, 
+                                  pdev->bus, pdev->devfn);
     return 0;
 }
 
@@ -454,7 +487,8 @@ static int amd_iommu_remove_device(struc
         return -ENODEV;
     }
 
-    amd_iommu_disable_domain_device(pdev->domain, iommu, bdf);
+    amd_iommu_disable_domain_device(pdev->domain, iommu, 
+                                    pdev->bus, pdev->devfn);
     return 0;
 }
 
diff -r 6009089b0511 -r 1ccad89116b5 
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     Fri Oct 21 14:50:23 
2011 +0200
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     Fri Oct 21 14:50:24 
2011 +0200
@@ -75,6 +75,7 @@ void amd_iommu_set_intremap_table(
     u32 *dte, u64 intremap_ptr, u8 int_valid);
 void amd_iommu_set_root_page_table(
     u32 *dte, u64 root_ptr, u16 domain_id, u8 paging_mode, u8 valid);
+void iommu_dte_set_iotlb(u32 *dte, u8 i);
 void invalidate_dev_table_entry(struct amd_iommu *iommu, u16 devic_id);
 
 /* send cmd to iommu */


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


 


Rackspace

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