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

[Xen-devel] [PATCH RFC v3 13/14] AMD/IOMMU: correct IRTE updating


  • To: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Jan Beulich <JBeulich@xxxxxxxx>
  • Date: Tue, 16 Jul 2019 16:40:58 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1;spf=pass smtp.mailfrom=suse.com;dmarc=pass action=none header.from=suse.com;dkim=pass header.d=suse.com;arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=pa4iProVUTIMZDm9RNd8EedGMivZSaJ2SgRN3Q/rP0g=; b=dQrtD0UHcok05WHlGCeBUoNYFc30cdllZM4ShsPVJp4gdYoW47WwsyeattW0ABD9BEN5NraZDO4U6fNLLKqOtgPCCE/xnWZATcjgajV0conbMIBLSXw516GMOIpUQJ/8mQkvGZu8xIpexNOcEoxJVUdOfAVPV583LUd+HyiCpnMSUmuCs8EAlPFx9asJ5LIBhMM56LOCBoz6QdX2AN7Gihd43yom9GyKjQU7SLNQv3WuvTZhcT3oBW/ytN8v/CCtGikLkvmujqPN1zanqvl5HtVvvAdQmsaEgyxL9tLKsBLIVZ6J6Pe1ib+qYd/5CnWyNEpevA733Zg/y4kc/X/Mbg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nlnSBen0K4moKmNz4ej4gWr33vQPsDIYWDGefFzPghyrrcVhTfZ9hCZ5xaCk+LFidCpzcxhujpMMe4nQ2w9eLxq8z3EDRVXRc2u9sbtEkTbPUvfVfQn91bWzL5t0XLfmNCpc4OXNUqu94SNfxaEsuuwzm4OwrLtGFJifBgmbQWvnRDvA4sLA9miNh9Arbd2m9BLexGNUXYfa2QuLsBdFRXiAhg00R8Qax1dHMGOBtxHyVmOXQNSWIbSlwLAap2qbEjH6s+ztBmTrHl7afq5+MSskGEkwYb1cdHKE0K86Pzrtrr6io2jqaZcqOQT2ZtbxxQ6IJE/TdcG/7Ts4UTFRzg==
  • Authentication-results: spf=none (sender IP is ) smtp.mailfrom=JBeulich@xxxxxxxx;
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Brian Woods <brian.woods@xxxxxxx>, Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
  • Delivery-date: Tue, 16 Jul 2019 16:41:20 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHVO/U+AyGNFXRfrkOVPYzWeacU2A==
  • Thread-topic: [PATCH RFC v3 13/14] AMD/IOMMU: correct IRTE updating

Flushing didn't get done along the lines of what the specification says.
Mark entries to be updated as not remapped (which will result in
interrupt requests to get target aborted, but the interrupts should be
masked anyway at that point in time), issue the flush, and only then
write the new entry.

In update_intremap_entry_from_msi_msg() also fold the duplicate initial
lock determination and acquire into just a single instance.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
RFC: Putting the flush invocations in loops isn't overly nice, but I
      don't think this can really be abused, since callers up the stack
      hold further locks. Nevertheless I'd like to ask for better
      suggestions.
---
v3: Remove stale parts of description. Re-base.
v2: Parts morphed into earlier patch.

--- a/xen/drivers/passthrough/amd/iommu_intr.c
+++ b/xen/drivers/passthrough/amd/iommu_intr.c
@@ -207,9 +207,7 @@ static void update_intremap_entry(const
              .vector = vector,
          };
  
-        ACCESS_ONCE(entry.ptr128->raw[0]) = 0;
-        /* Low half, in particular RemapEn, needs to be cleared first. */
-        barrier();
+        ASSERT(!entry.ptr128->full.remap_en);
          entry.ptr128->raw[1] =
              container_of(&full, union irte128, full)->raw[1];
          /* High half needs to be set before low one (containing RemapEn). */
@@ -288,6 +286,20 @@ static int update_intremap_entry_from_io
      }
  
      entry = get_intremap_entry(iommu, req_id, offset);
+
+    /* The RemapEn fields match for all formats. */
+    while ( iommu->enabled && entry.ptr32->basic.remap_en )
+    {
+        entry.ptr32->basic.remap_en = false;
+        spin_unlock(lock);
+
+        spin_lock(&iommu->lock);
+        amd_iommu_flush_intremap(iommu, req_id);
+        spin_unlock(&iommu->lock);
+
+        spin_lock(lock);
+    }
+
      if ( fresh )
          /* nothing */;
      else if ( !lo_update )
@@ -317,13 +329,6 @@ static int update_intremap_entry_from_io
  
      spin_unlock_irqrestore(lock, flags);
  
-    if ( iommu->enabled && !fresh )
-    {
-        spin_lock_irqsave(&iommu->lock, flags);
-        amd_iommu_flush_intremap(iommu, req_id);
-        spin_unlock_irqrestore(&iommu->lock, flags);
-    }
-
      set_rte_index(rte, offset);
  
      return 0;
@@ -579,19 +584,27 @@ static int update_intremap_entry_from_ms
      req_id = get_dma_requestor_id(iommu->seg, bdf);
      alias_id = get_intremap_requestor_id(iommu->seg, bdf);
  
+    lock = get_intremap_lock(iommu->seg, req_id);
+    spin_lock_irqsave(lock, flags);
+
      if ( msg == NULL )
      {
-        lock = get_intremap_lock(iommu->seg, req_id);
-        spin_lock_irqsave(lock, flags);
          for ( i = 0; i < nr; ++i )
              free_intremap_entry(iommu, req_id, *remap_index + i);
          spin_unlock_irqrestore(lock, flags);
-        goto done;
-    }
  
-    lock = get_intremap_lock(iommu->seg, req_id);
+        if ( iommu->enabled )
+        {
+            spin_lock_irqsave(&iommu->lock, flags);
+            amd_iommu_flush_intremap(iommu, req_id);
+            if ( alias_id != req_id )
+                amd_iommu_flush_intremap(iommu, alias_id);
+            spin_unlock_irqrestore(&iommu->lock, flags);
+        }
+
+        return 0;
+    }
  
-    spin_lock_irqsave(lock, flags);
      dest_mode = (msg->address_lo >> MSI_ADDR_DESTMODE_SHIFT) & 0x1;
      delivery_mode = (msg->data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x1;
      vector = (msg->data >> MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK;
@@ -615,6 +628,22 @@ static int update_intremap_entry_from_ms
      }
  
      entry = get_intremap_entry(iommu, req_id, offset);
+
+    /* The RemapEn fields match for all formats. */
+    while ( iommu->enabled && entry.ptr32->basic.remap_en )
+    {
+        entry.ptr32->basic.remap_en = false;
+        spin_unlock(lock);
+
+        spin_lock(&iommu->lock);
+        amd_iommu_flush_intremap(iommu, req_id);
+        if ( alias_id != req_id )
+            amd_iommu_flush_intremap(iommu, alias_id);
+        spin_unlock(&iommu->lock);
+
+        spin_lock(lock);
+    }
+
      update_intremap_entry(iommu, entry, vector, delivery_mode, dest_mode, 
dest);
      spin_unlock_irqrestore(lock, flags);
  
@@ -634,16 +663,6 @@ static int update_intremap_entry_from_ms
                 get_ivrs_mappings(iommu->seg)[alias_id].intremap_table);
      }
  
-done:
-    if ( iommu->enabled )
-    {
-        spin_lock_irqsave(&iommu->lock, flags);
-        amd_iommu_flush_intremap(iommu, req_id);
-        if ( alias_id != req_id )
-            amd_iommu_flush_intremap(iommu, alias_id);
-        spin_unlock_irqrestore(&iommu->lock, flags);
-    }
-
      return 0;
  }
  

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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