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-devel

[Xen-devel] [PATCH 5 of 5] amd iommu: enable ats devices

To: <JanJBeulich@xxxxxxxx>
Subject: [Xen-devel] [PATCH 5 of 5] amd iommu: enable ats devices
From: Wei Wang <wei.wang2@xxxxxxx>
Date: Thu, 3 Nov 2011 16:48:52 +0100
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx
Delivery-date: Thu, 03 Nov 2011 08:55:21 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1320335327@xxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <patchbomb.1320335327@xxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1.9.3
# HG changeset patch
# User Wei Wang <wei.wang2@xxxxxxx>
# Date 1320334827 -3600
# Node ID 59b7d9f9b571d6de35e5c5dae81a3890752271fe
# Parent  acfe5b608724cb06c644a61b73599c748a81274a
amd iommu: enable ats devices

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

diff -r acfe5b608724 -r 59b7d9f9b571 xen/drivers/passthrough/amd/iommu_map.c
--- a/xen/drivers/passthrough/amd/iommu_map.c   Thu Nov 03 16:39:43 2011 +0100
+++ b/xen/drivers/passthrough/amd/iommu_map.c   Thu Nov 03 16:40:27 2011 +0100
@@ -370,6 +370,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 acfe5b608724 -r 59b7d9f9b571 xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c       Thu Nov 03 16:39:43 
2011 +0100
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c       Thu Nov 03 16:40:27 
2011 +0100
@@ -25,6 +25,7 @@
 #include <asm/hvm/iommu.h>
 #include <asm/amd-iommu.h>
 #include <asm/hvm/svm/amd-iommu-proto.h>
+#include "../ats.h"
 
 struct amd_iommu *find_iommu_for_device(int seg, int bdf)
 {
@@ -86,6 +87,9 @@ static void amd_iommu_setup_domain_devic
     void *dte;
     unsigned long flags;
     int req_id, valid = 1;
+    int dte_i = 0;
+    u8 bus = PCI_BUS(bdf);
+    u8 devfn = PCI_DEVFN2(bdf);
 
     struct hvm_iommu *hd = domain_hvm_iommu(domain);
 
@@ -94,6 +98,9 @@ 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);
     dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
@@ -107,6 +114,10 @@ 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,11 +129,27 @@ 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) &&
+         !pci_ats_enabled(iommu->seg, bus, devfn) )
+    {
+        struct pci_dev *pdev;
+
+        enable_ats_device(iommu->seg, bus, devfn);
+
+        ASSERT(spin_is_locked(&pcidevs_lock));
+        pdev = pci_get_pdev(iommu->seg, bus, devfn);
+
+        ASSERT( pdev != NULL );
+        amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
+    }
 }
 
 static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev)
 {
-    int bdf = (pdev->bus << 8) | pdev->devfn;
+    int bdf = PCI_BDF2(pdev->bus, pdev->devfn);
     struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
 
     if ( likely(iommu != NULL) )
@@ -261,12 +288,14 @@ 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, int bdf)
 {
     void *dte;
     unsigned long flags;
     int req_id;
+    u8 bus = PCI_BUS(bdf);
+    u8 devfn = PCI_DEVFN2(bdf);
 
     BUG_ON ( iommu->dev_table.buffer == NULL );
     req_id = get_dma_requestor_id(iommu->seg, bdf);
@@ -276,6 +305,11 @@ static void amd_iommu_disable_domain_dev
     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 +318,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) && 
+         pci_ats_enabled(iommu->seg, bus, devfn) )
+       disable_ats_device(iommu->seg, bus, devfn); 
 }
 
 static int reassign_device( struct domain *source, struct domain *target,
@@ -299,7 +339,7 @@ static int reassign_device( struct domai
     if ( !pdev )
         return -ENODEV;
 
-    bdf = (bus << 8) | devfn;
+    bdf = PCI_BDF2(bus, devfn);
     iommu = find_iommu_for_device(seg, bdf);
     if ( !iommu )
     {
@@ -421,7 +461,7 @@ static int amd_iommu_add_device(struct p
     if ( !pdev->domain )
         return -EINVAL;
 
-    bdf = (pdev->bus << 8) | pdev->devfn;
+    bdf = PCI_BDF2(pdev->bus, pdev->devfn);
     iommu = find_iommu_for_device(pdev->seg, bdf);
     if ( !iommu )
     {
@@ -443,7 +483,7 @@ static int amd_iommu_remove_device(struc
     if ( !pdev->domain )
         return -EINVAL;
 
-    bdf = (pdev->bus << 8) | pdev->devfn;
+    bdf = PCI_BDF2(pdev->bus, pdev->devfn);
     iommu = find_iommu_for_device(pdev->seg, bdf);
     if ( !iommu )
     {
diff -r acfe5b608724 -r 59b7d9f9b571 
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     Thu Nov 03 16:39:43 
2011 +0100
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     Thu Nov 03 16:40:27 
2011 +0100
@@ -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