qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/7] Some vIOMMU fixes
@ 2021-02-25  9:14 Eric Auger
  2021-02-25  9:14 ` [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate Eric Auger
                   ` (6 more replies)
  0 siblings, 7 replies; 19+ messages in thread
From: Eric Auger @ 2021-02-25  9:14 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

Hi,

Here is a set of vIOMMU fixes:

SMMUv3:
- top SID computation overflow when handling SMMU_CMD_CFGI_ALL
- internal IOTLB handling (changes related to range invalidation)
  - smmu_iotlb_inv_iova with asid = -1
  - non power of 2 invalidation range handling.

VIRTIO-IOMMU:
  - non power of 2 invalidation range handling.

Best Regards

Eric

v2: https://github.com/eauger/qemu/tree/viommu_fixes_for_6-v2
v1: https://github.com/eauger/qemu/tree/viommu_fixes_for_6

History:
v1 -> v2:
- new:
  - dma: Introduce dma_aligned_pow2_mask()
  - intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
  - hw/arm/smmuv3: Uniformize sid traces

Eric Auger (7):
  intel_iommu: Fix mask may be uninitialized in
    vtd_context_device_invalidate
  dma: Introduce dma_aligned_pow2_mask()
  virtio-iommu: Handle non power of 2 range invalidations
  hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set
  hw/arm/smmuv3: Enforce invalidation on a power of two range
  hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling
  hw/arm/smmuv3: Uniformize sid traces

 hw/arm/smmu-common.c     | 32 +++++++++++++---------
 hw/arm/smmu-internal.h   |  5 ++++
 hw/arm/smmuv3.c          | 58 +++++++++++++++++++++++++++-------------
 hw/arm/trace-events      | 24 ++++++++---------
 hw/i386/intel_iommu.c    | 32 +++++++---------------
 hw/virtio/virtio-iommu.c | 19 ++++++++++---
 include/sysemu/dma.h     |  3 +++
 softmmu/dma-helpers.c    | 26 ++++++++++++++++++
 8 files changed, 130 insertions(+), 69 deletions(-)

-- 
2.26.2



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
  2021-02-25  9:14 [PATCH v2 0/7] Some vIOMMU fixes Eric Auger
@ 2021-02-25  9:14 ` Eric Auger
  2021-02-25 10:08   ` Philippe Mathieu-Daudé
  2021-02-25 15:41   ` Peter Xu
  2021-02-25  9:14 ` [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask() Eric Auger
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Eric Auger @ 2021-02-25  9:14 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

With -Werror=maybe-uninitialized configuration we get
../hw/i386/intel_iommu.c: In function ‘vtd_context_device_invalidate’:
../hw/i386/intel_iommu.c:1888:10: error: ‘mask’ may be used
uninitialized in this function [-Werror=maybe-uninitialized]
 1888 |     mask = ~mask;
      |     ~~~~~^~~~~~~

Add a g_assert_not_reached() to avoid the error.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 hw/i386/intel_iommu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index b4f5094259..3206f379f8 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -1884,6 +1884,8 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
     case 3:
         mask = 7;   /* Mask bit 2:0 in the SID field */
         break;
+    default:
+        g_assert_not_reached();
     }
     mask = ~mask;
 
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask()
  2021-02-25  9:14 [PATCH v2 0/7] Some vIOMMU fixes Eric Auger
  2021-02-25  9:14 ` [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate Eric Auger
@ 2021-02-25  9:14 ` Eric Auger
  2021-02-25 15:56   ` Peter Xu
  2021-03-08 16:34   ` Peter Maydell
  2021-02-25  9:14 ` [PATCH v2 3/7] virtio-iommu: Handle non power of 2 range invalidations Eric Auger
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 19+ messages in thread
From: Eric Auger @ 2021-02-25  9:14 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

Currently get_naturally_aligned_size() is used by the intel iommu
to compute the maximum invalidation range based on @size which is
a power of 2 while being aligned with the @start address and less
than the maximum range defined by @gaw.

This helper is also useful for other iommu devices (virtio-iommu,
SMMUv3) to make sure IOMMU UNMAP notifiers only are called with
power of 2 range sizes.

Let's move this latter into dma-helpers.c and rename it into
dma_aligned_pow2_mask(). Also rewrite the helper so that it
accomodates UINT64_MAX values for the size mask and max mask.
It now returns a mask instead of a size. Change the caller.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 hw/i386/intel_iommu.c | 30 +++++++-----------------------
 include/sysemu/dma.h  |  3 +++
 softmmu/dma-helpers.c | 26 ++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 3206f379f8..6be8f32918 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -35,6 +35,7 @@
 #include "hw/i386/x86-iommu.h"
 #include "hw/pci-host/q35.h"
 #include "sysemu/kvm.h"
+#include "sysemu/dma.h"
 #include "sysemu/sysemu.h"
 #include "hw/i386/apic_internal.h"
 #include "kvm/kvm_i386.h"
@@ -3455,24 +3456,6 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
     return vtd_dev_as;
 }
 
-static uint64_t get_naturally_aligned_size(uint64_t start,
-                                           uint64_t size, int gaw)
-{
-    uint64_t max_mask = 1ULL << gaw;
-    uint64_t alignment = start ? start & -start : max_mask;
-
-    alignment = MIN(alignment, max_mask);
-    size = MIN(size, max_mask);
-
-    if (alignment <= size) {
-        /* Increase the alignment of start */
-        return alignment;
-    } else {
-        /* Find the largest page mask from size */
-        return 1ULL << (63 - clz64(size));
-    }
-}
-
 /* Unmap the whole range in the notifier's scope. */
 static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
 {
@@ -3501,13 +3484,14 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
 
     while (remain >= VTD_PAGE_SIZE) {
         IOMMUTLBEvent event;
-        uint64_t mask = get_naturally_aligned_size(start, remain, s->aw_bits);
+        uint64_t mask = dma_aligned_pow2_mask(start, end, s->aw_bits);
+        uint64_t size = mask + 1;
 
-        assert(mask);
+        assert(size);
 
         event.type = IOMMU_NOTIFIER_UNMAP;
         event.entry.iova = start;
-        event.entry.addr_mask = mask - 1;
+        event.entry.addr_mask = mask;
         event.entry.target_as = &address_space_memory;
         event.entry.perm = IOMMU_NONE;
         /* This field is meaningless for unmap */
@@ -3515,8 +3499,8 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
 
         memory_region_notify_iommu_one(n, &event);
 
-        start += mask;
-        remain -= mask;
+        start += size;
+        remain -= size;
     }
 
     assert(!remain);
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index a052f7bca3..2acb303be2 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -296,4 +296,7 @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
 void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
                     QEMUSGList *sg, enum BlockAcctType type);
 
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end,
+                               int max_addr_bits);
+
 #endif
diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c
index 29001b5459..7d766a5e89 100644
--- a/softmmu/dma-helpers.c
+++ b/softmmu/dma-helpers.c
@@ -330,3 +330,29 @@ void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
 {
     block_acct_start(blk_get_stats(blk), cookie, sg->size, type);
 }
+
+uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end, int max_addr_bits)
+{
+    uint64_t max_mask = UINT64_MAX, addr_mask = end - start;
+    uint64_t alignment_mask, size_mask;
+
+    if (max_addr_bits != 64) {
+        max_mask = (1ULL << max_addr_bits) - 1;
+    }
+
+    alignment_mask = start ? (start & -start) - 1 : max_mask;
+    alignment_mask = MIN(alignment_mask, max_mask);
+    size_mask = MIN(addr_mask, max_mask);
+
+    if (alignment_mask <= size_mask) {
+        /* Increase the alignment of start */
+        return alignment_mask;
+    } else {
+        /* Find the largest page mask from size */
+        if (addr_mask == UINT64_MAX) {
+            return UINT64_MAX;
+        }
+        return (1ULL << (63 - clz64(addr_mask + 1))) - 1;
+    }
+}
+
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 3/7] virtio-iommu: Handle non power of 2 range invalidations
  2021-02-25  9:14 [PATCH v2 0/7] Some vIOMMU fixes Eric Auger
  2021-02-25  9:14 ` [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate Eric Auger
  2021-02-25  9:14 ` [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask() Eric Auger
@ 2021-02-25  9:14 ` Eric Auger
  2021-02-25 16:01   ` Peter Xu
  2021-02-25  9:14 ` [PATCH v2 4/7] hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set Eric Auger
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Eric Auger @ 2021-02-25  9:14 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

Unmap notifiers work with an address mask assuming an
invalidation range of a power of 2. Nothing mandates this
in the VIRTIO-IOMMU spec.

So in case the range is not a power of 2, split it into
several invalidations.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 hw/virtio/virtio-iommu.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index c2883a2f6c..1b23e8e18c 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -155,6 +155,7 @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
                                       hwaddr virt_end)
 {
     IOMMUTLBEvent event;
+    uint64_t delta = virt_end - virt_start;
 
     if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) {
         return;
@@ -164,12 +165,24 @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start,
 
     event.type = IOMMU_NOTIFIER_UNMAP;
     event.entry.target_as = &address_space_memory;
-    event.entry.addr_mask = virt_end - virt_start;
-    event.entry.iova = virt_start;
     event.entry.perm = IOMMU_NONE;
     event.entry.translated_addr = 0;
+    event.entry.addr_mask = delta;
+    event.entry.iova = virt_start;
 
-    memory_region_notify_iommu(mr, 0, event);
+    if (delta == UINT64_MAX) {
+        memory_region_notify_iommu(mr, 0, event);
+    }
+
+
+    while (virt_start != virt_end + 1) {
+        uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64);
+
+        event.entry.addr_mask = mask;
+        event.entry.iova = virt_start;
+        memory_region_notify_iommu(mr, 0, event);
+        virt_start += mask + 1;
+    }
 }
 
 static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value,
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 4/7] hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set
  2021-02-25  9:14 [PATCH v2 0/7] Some vIOMMU fixes Eric Auger
                   ` (2 preceding siblings ...)
  2021-02-25  9:14 ` [PATCH v2 3/7] virtio-iommu: Handle non power of 2 range invalidations Eric Auger
@ 2021-02-25  9:14 ` Eric Auger
  2021-03-08 16:37   ` Peter Maydell
  2021-02-25  9:14 ` [PATCH v2 5/7] hw/arm/smmuv3: Enforce invalidation on a power of two range Eric Auger
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 19+ messages in thread
From: Eric Auger @ 2021-02-25  9:14 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

If the asid is not set, do not attempt to locate the key directly
as all inserted keys have a valid asid.

Use g_hash_table_foreach_remove instead.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 hw/arm/smmu-common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index 405d5c5325..e9ca3aebb2 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -151,7 +151,7 @@ inline void
 smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
                     uint8_t tg, uint64_t num_pages, uint8_t ttl)
 {
-    if (ttl && (num_pages == 1)) {
+    if (ttl && (num_pages == 1) && (asid >= 0)) {
         SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
 
         g_hash_table_remove(s->iotlb, &key);
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 5/7] hw/arm/smmuv3: Enforce invalidation on a power of two range
  2021-02-25  9:14 [PATCH v2 0/7] Some vIOMMU fixes Eric Auger
                   ` (3 preceding siblings ...)
  2021-02-25  9:14 ` [PATCH v2 4/7] hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set Eric Auger
@ 2021-02-25  9:14 ` Eric Auger
  2021-03-08 16:44   ` Peter Maydell
  2021-02-25  9:14 ` [PATCH v2 6/7] hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling Eric Auger
  2021-02-25  9:14 ` [PATCH v2 7/7] hw/arm/smmuv3: Uniformize sid traces Eric Auger
  6 siblings, 1 reply; 19+ messages in thread
From: Eric Auger @ 2021-02-25  9:14 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

As of today, the driver can invalide a number of pages that is
not a power of 2. However IOTLB unmap notifications and internal
IOTLB invalidations work with masks leading to erroneous
invalidations.

In case the range is not a power of 2, split invalidations into
power of 2 invalidations.

When looking for a single page entry in the vSMMU internal IOTLB,
let's make sure that if the entry is not found using a
g_hash_table_remove() we iterate over all the entries to find a
potential range that overlaps it.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 hw/arm/smmu-common.c | 30 ++++++++++++++++++------------
 hw/arm/smmuv3.c      | 24 ++++++++++++++++++++----
 2 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index e9ca3aebb2..84d2c62c26 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -151,22 +151,28 @@ inline void
 smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
                     uint8_t tg, uint64_t num_pages, uint8_t ttl)
 {
+    /* if tg is not set we use 4KB range invalidation */
+    uint8_t granule = tg ? tg * 2 + 10 : 12;
+
     if (ttl && (num_pages == 1) && (asid >= 0)) {
         SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
 
-        g_hash_table_remove(s->iotlb, &key);
-    } else {
-        /* if tg is not set we use 4KB range invalidation */
-        uint8_t granule = tg ? tg * 2 + 10 : 12;
-
-        SMMUIOTLBPageInvInfo info = {
-            .asid = asid, .iova = iova,
-            .mask = (num_pages * 1 << granule) - 1};
-
-        g_hash_table_foreach_remove(s->iotlb,
-                                    smmu_hash_remove_by_asid_iova,
-                                    &info);
+        if (g_hash_table_remove(s->iotlb, &key)) {
+            return;
+        }
+        /*
+         * if the entry is not found, let's see if it does not
+         * belong to a larger IOTLB entry
+         */
     }
+
+    SMMUIOTLBPageInvInfo info = {
+        .asid = asid, .iova = iova,
+        .mask = (num_pages * 1 << granule) - 1};
+
+    g_hash_table_foreach_remove(s->iotlb,
+                                smmu_hash_remove_by_asid_iova,
+                                &info);
 }
 
 inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index bd1f97000d..fdd6332ce5 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -861,7 +861,8 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
     uint16_t vmid = CMD_VMID(cmd);
     bool leaf = CMD_LEAF(cmd);
     uint8_t tg = CMD_TG(cmd);
-    hwaddr num_pages = 1;
+    uint64_t first_page = 0, last_page;
+    uint64_t num_pages = 1;
     int asid = -1;
 
     if (tg) {
@@ -874,9 +875,24 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
     if (type == SMMU_CMD_TLBI_NH_VA) {
         asid = CMD_ASID(cmd);
     }
-    trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
-    smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
-    smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
+
+    /* Split invalidations into ^2 range invalidations */
+    last_page = num_pages - 1;
+    while (num_pages) {
+        uint8_t granule = tg * 2 + 10;
+        uint64_t mask, count;
+
+        mask = dma_aligned_pow2_mask(first_page, last_page, 64 - granule);
+        count = mask + 1;
+
+        trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, count, ttl, leaf);
+        smmuv3_inv_notifiers_iova(s, asid, addr, tg, count);
+        smmu_iotlb_inv_iova(s, asid, addr, tg, count, ttl);
+
+        num_pages -= count;
+        first_page += count;
+        addr += count * BIT_ULL(granule);
+    }
 }
 
 static int smmuv3_cmdq_consume(SMMUv3State *s)
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 6/7] hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling
  2021-02-25  9:14 [PATCH v2 0/7] Some vIOMMU fixes Eric Auger
                   ` (4 preceding siblings ...)
  2021-02-25  9:14 ` [PATCH v2 5/7] hw/arm/smmuv3: Enforce invalidation on a power of two range Eric Auger
@ 2021-02-25  9:14 ` Eric Auger
  2021-03-08 16:41   ` Peter Maydell
  2021-02-25  9:14 ` [PATCH v2 7/7] hw/arm/smmuv3: Uniformize sid traces Eric Auger
  6 siblings, 1 reply; 19+ messages in thread
From: Eric Auger @ 2021-02-25  9:14 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

If the whole SID range (32b) is invalidated (SMMU_CMD_CFGI_ALL),
@end overflows and we fail to handle the command properly.

Once this gets fixed, the current code really is awkward in the
sense it loops over the whole range instead of removing the
currently cached configs through a hash table lookup.

Fix both the overflow and the lookup.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 hw/arm/smmu-internal.h |  5 +++++
 hw/arm/smmuv3.c        | 34 ++++++++++++++++++++--------------
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
index 55147f29be..2d75b31953 100644
--- a/hw/arm/smmu-internal.h
+++ b/hw/arm/smmu-internal.h
@@ -104,4 +104,9 @@ typedef struct SMMUIOTLBPageInvInfo {
     uint64_t mask;
 } SMMUIOTLBPageInvInfo;
 
+typedef struct SMMUSIDRange {
+    uint32_t start;
+    uint32_t end;
+} SMMUSIDRange;
+
 #endif
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index fdd6332ce5..3b87324ce2 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -32,6 +32,7 @@
 
 #include "hw/arm/smmuv3.h"
 #include "smmuv3-internal.h"
+#include "smmu-internal.h"
 
 /**
  * smmuv3_trigger_irq - pulse @irq if enabled and update
@@ -895,6 +896,20 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
     }
 }
 
+static gboolean
+smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
+{
+    SMMUDevice *sdev = (SMMUDevice *)key;
+    uint32_t sid = smmu_get_sid(sdev);
+    SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
+
+    if (sid < sid_range->start || sid > sid_range->end) {
+        return false;
+    }
+    trace_smmuv3_config_cache_inv(sid);
+    return true;
+}
+
 static int smmuv3_cmdq_consume(SMMUv3State *s)
 {
     SMMUState *bs = ARM_SMMU(s);
@@ -965,27 +980,18 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
         }
         case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */
         {
-            uint32_t start = CMD_SID(&cmd), end, i;
+            uint32_t start = CMD_SID(&cmd);
             uint8_t range = CMD_STE_RANGE(&cmd);
+            uint64_t end = start + (1ULL << (range + 1)) - 1;
+            SMMUSIDRange sid_range = {start, end};
 
             if (CMD_SSEC(&cmd)) {
                 cmd_error = SMMU_CERROR_ILL;
                 break;
             }
-
-            end = start + (1 << (range + 1)) - 1;
             trace_smmuv3_cmdq_cfgi_ste_range(start, end);
-
-            for (i = start; i <= end; i++) {
-                IOMMUMemoryRegion *mr = smmu_iommu_mr(bs, i);
-                SMMUDevice *sdev;
-
-                if (!mr) {
-                    continue;
-                }
-                sdev = container_of(mr, SMMUDevice, iommu);
-                smmuv3_flush_config(sdev);
-            }
+            g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
+                                        &sid_range);
             break;
         }
         case SMMU_CMD_CFGI_CD:
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v2 7/7] hw/arm/smmuv3: Uniformize sid traces
  2021-02-25  9:14 [PATCH v2 0/7] Some vIOMMU fixes Eric Auger
                   ` (5 preceding siblings ...)
  2021-02-25  9:14 ` [PATCH v2 6/7] hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling Eric Auger
@ 2021-02-25  9:14 ` Eric Auger
  2021-02-25 10:11   ` Philippe Mathieu-Daudé
  6 siblings, 1 reply; 19+ messages in thread
From: Eric Auger @ 2021-02-25  9:14 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

Convert all sid printouts to sid=0x%x.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 hw/arm/trace-events | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/hw/arm/trace-events b/hw/arm/trace-events
index a335ee891d..b79a91af5f 100644
--- a/hw/arm/trace-events
+++ b/hw/arm/trace-events
@@ -29,26 +29,26 @@ smmuv3_cmdq_opcode(const char *opcode) "<--- %s"
 smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d "
 smmuv3_cmdq_consume_error(const char *cmd_name, uint8_t cmd_error) "Error on %s command execution: %d"
 smmuv3_write_mmio(uint64_t addr, uint64_t val, unsigned size, uint32_t r) "addr: 0x%"PRIx64" val:0x%"PRIx64" size: 0x%x(%d)"
-smmuv3_record_event(const char *type, uint32_t sid) "%s sid=%d"
-smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:0x%x features:0x%x, sid_split:0x%x"
+smmuv3_record_event(const char *type, uint32_t sid) "%s sid=0x%x"
+smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "sid=0x%x features:0x%x, sid_split:0x%x"
 smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offset, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%"PRIx64" l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_ste:%d"
 smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64
-smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
-smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d STE bypass iova:0x%"PRIx64" is_write=%d"
-smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=%d abort on iova:0x%"PRIx64" is_write=%d"
-smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=%d iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
+smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x bypass (smmu disabled) iova:0x%"PRIx64" is_write=%d"
+smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x STE bypass iova:0x%"PRIx64" is_write=%d"
+smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is_write) "%s sid=0x%x abort on iova:0x%"PRIx64" is_write=%d"
+smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint64_t translated, int perm) "%s sid=0x%x iova=0x%"PRIx64" translated=0x%"PRIx64" perm=0x%x"
 smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64
 smmuv3_decode_cd(uint32_t oas) "oas=%d"
 smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz, bool had) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d had:%d"
-smmuv3_cmdq_cfgi_ste(int streamid) "streamid =%d"
+smmuv3_cmdq_cfgi_ste(int streamid) "streamid= 0x%x"
 smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%x - end=0x%x"
-smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
-smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
-smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
-smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
+smmuv3_cmdq_cfgi_cd(uint32_t sid) "sid=0x%x"
+smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid=0x%x (hits=%d, misses=%d, hit rate=%d)"
+smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid=0x%x (hits=%d, misses=%d, hit rate=%d)"
+smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid=%d asid=%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
 smmuv3_cmdq_tlbi_nh(void) ""
 smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
-smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
+smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
 smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
 smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
 smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
  2021-02-25  9:14 ` [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate Eric Auger
@ 2021-02-25 10:08   ` Philippe Mathieu-Daudé
  2021-02-25 16:33     ` Auger Eric
  2021-02-25 15:41   ` Peter Xu
  1 sibling, 1 reply; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-25 10:08 UTC (permalink / raw)
  To: Eric Auger, eric.auger.pro, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

On 2/25/21 10:14 AM, Eric Auger wrote:
> With -Werror=maybe-uninitialized configuration we get
> ../hw/i386/intel_iommu.c: In function ‘vtd_context_device_invalidate’:
> ../hw/i386/intel_iommu.c:1888:10: error: ‘mask’ may be used
> uninitialized in this function [-Werror=maybe-uninitialized]
>  1888 |     mask = ~mask;
>       |     ~~~~~^~~~~~~
> 
> Add a g_assert_not_reached() to avoid the error.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  hw/i386/intel_iommu.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
> index b4f5094259..3206f379f8 100644
> --- a/hw/i386/intel_iommu.c
> +++ b/hw/i386/intel_iommu.c
> @@ -1884,6 +1884,8 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
>      case 3:
>          mask = 7;   /* Mask bit 2:0 in the SID field */
>          break;
> +    default:
> +        g_assert_not_reached();
>      }
>      mask = ~mask;

Unrelated to this patch, but I wonder why we don't directly assign the
correct value of the mask in the switch cases...

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>

set the mask
diuse the
>  
> 



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 7/7] hw/arm/smmuv3: Uniformize sid traces
  2021-02-25  9:14 ` [PATCH v2 7/7] hw/arm/smmuv3: Uniformize sid traces Eric Auger
@ 2021-02-25 10:11   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 19+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-02-25 10:11 UTC (permalink / raw)
  To: Eric Auger, eric.auger.pro, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

On 2/25/21 10:14 AM, Eric Auger wrote:
> Convert all sid printouts to sid=0x%x.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  hw/arm/trace-events | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
  2021-02-25  9:14 ` [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate Eric Auger
  2021-02-25 10:08   ` Philippe Mathieu-Daudé
@ 2021-02-25 15:41   ` Peter Xu
  1 sibling, 0 replies; 19+ messages in thread
From: Peter Xu @ 2021-02-25 15:41 UTC (permalink / raw)
  To: Eric Auger
  Cc: peter.maydell, jean-philippe, jasowang, qemu-devel,
	shameerali.kolothum.thodi, vivek.gautam, qemu-arm, pbonzini,
	eric.auger.pro

On Thu, Feb 25, 2021 at 10:14:29AM +0100, Eric Auger wrote:
> With -Werror=maybe-uninitialized configuration we get
> ../hw/i386/intel_iommu.c: In function ‘vtd_context_device_invalidate’:
> ../hw/i386/intel_iommu.c:1888:10: error: ‘mask’ may be used
> uninitialized in this function [-Werror=maybe-uninitialized]
>  1888 |     mask = ~mask;
>       |     ~~~~~^~~~~~~
> 
> Add a g_assert_not_reached() to avoid the error.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Reviewed-by: Peter Xu <peterx@redhat.com>

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask()
  2021-02-25  9:14 ` [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask() Eric Auger
@ 2021-02-25 15:56   ` Peter Xu
  2021-03-08 16:34   ` Peter Maydell
  1 sibling, 0 replies; 19+ messages in thread
From: Peter Xu @ 2021-02-25 15:56 UTC (permalink / raw)
  To: Eric Auger
  Cc: peter.maydell, jean-philippe, jasowang, qemu-devel,
	shameerali.kolothum.thodi, vivek.gautam, qemu-arm, pbonzini,
	eric.auger.pro

On Thu, Feb 25, 2021 at 10:14:30AM +0100, Eric Auger wrote:
> @@ -296,4 +296,7 @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
>  void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
>                      QEMUSGList *sg, enum BlockAcctType type);
>  
> +uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end,
> +                               int max_addr_bits);
> +
>  #endif
> diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c
> index 29001b5459..7d766a5e89 100644
> --- a/softmmu/dma-helpers.c
> +++ b/softmmu/dma-helpers.c
> @@ -330,3 +330,29 @@ void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
>  {
>      block_acct_start(blk_get_stats(blk), cookie, sg->size, type);
>  }
> +
> +uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end, int max_addr_bits)

Nitpick: If to make it a common function, shall we comment the interface to
avoid misusing it? E.g., start/end seem to be inclusive. Also, max_addr_bits
should be <=64 (and we can also assert in the code, maybe?).

> +{
> +    uint64_t max_mask = UINT64_MAX, addr_mask = end - start;
> +    uint64_t alignment_mask, size_mask;
> +
> +    if (max_addr_bits != 64) {
> +        max_mask = (1ULL << max_addr_bits) - 1;
> +    }
> +
> +    alignment_mask = start ? (start & -start) - 1 : max_mask;
> +    alignment_mask = MIN(alignment_mask, max_mask);
> +    size_mask = MIN(addr_mask, max_mask);
> +
> +    if (alignment_mask <= size_mask) {
> +        /* Increase the alignment of start */
> +        return alignment_mask;
> +    } else {
> +        /* Find the largest page mask from size */
> +        if (addr_mask == UINT64_MAX) {
> +            return UINT64_MAX;
> +        }
> +        return (1ULL << (63 - clz64(addr_mask + 1))) - 1;
> +    }
> +}
> +

In all cases, the code looks right to me:

Reviewed-by: Peter Xu <peterx@redhat.com>

Thanks,

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 3/7] virtio-iommu: Handle non power of 2 range invalidations
  2021-02-25  9:14 ` [PATCH v2 3/7] virtio-iommu: Handle non power of 2 range invalidations Eric Auger
@ 2021-02-25 16:01   ` Peter Xu
  0 siblings, 0 replies; 19+ messages in thread
From: Peter Xu @ 2021-02-25 16:01 UTC (permalink / raw)
  To: Eric Auger
  Cc: peter.maydell, jean-philippe, jasowang, qemu-devel,
	shameerali.kolothum.thodi, vivek.gautam, qemu-arm, pbonzini,
	eric.auger.pro

On Thu, Feb 25, 2021 at 10:14:31AM +0100, Eric Auger wrote:
> Unmap notifiers work with an address mask assuming an
> invalidation range of a power of 2. Nothing mandates this
> in the VIRTIO-IOMMU spec.
> 
> So in case the range is not a power of 2, split it into
> several invalidations.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Reviewed-by: Peter Xu <peterx@redhat.com>

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate
  2021-02-25 10:08   ` Philippe Mathieu-Daudé
@ 2021-02-25 16:33     ` Auger Eric
  0 siblings, 0 replies; 19+ messages in thread
From: Auger Eric @ 2021-02-25 16:33 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé,
	eric.auger.pro, qemu-devel, qemu-arm, peter.maydell,
	jean-philippe, peterx, jasowang, pbonzini
  Cc: vivek.gautam, shameerali.kolothum.thodi

Hi Philippe,

On 2/25/21 11:08 AM, Philippe Mathieu-Daudé wrote:
> On 2/25/21 10:14 AM, Eric Auger wrote:
>> With -Werror=maybe-uninitialized configuration we get
>> ../hw/i386/intel_iommu.c: In function ‘vtd_context_device_invalidate’:
>> ../hw/i386/intel_iommu.c:1888:10: error: ‘mask’ may be used
>> uninitialized in this function [-Werror=maybe-uninitialized]
>>  1888 |     mask = ~mask;
>>       |     ~~~~~^~~~~~~
>>
>> Add a g_assert_not_reached() to avoid the error.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> ---
>>  hw/i386/intel_iommu.c | 2 ++
>>  1 file changed, 2 insertions(+)
>>
>> diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
>> index b4f5094259..3206f379f8 100644
>> --- a/hw/i386/intel_iommu.c
>> +++ b/hw/i386/intel_iommu.c
>> @@ -1884,6 +1884,8 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
>>      case 3:
>>          mask = 7;   /* Mask bit 2:0 in the SID field */
>>          break;
>> +    default:
>> +        g_assert_not_reached();
>>      }
>>      mask = ~mask;
> 
> Unrelated to this patch, but I wonder why we don't directly assign the
> correct value of the mask in the switch cases...

After reading the vtd spec again, I think this is aligned with the spec
description.  FM = function mask encodes the bits to mask. Then you
actually compute the mask by ~mask.
> 
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>

Thanks!

Eric

> 
> set the mask
> diuse the
>>  
>>
> 



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask()
  2021-02-25  9:14 ` [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask() Eric Auger
  2021-02-25 15:56   ` Peter Xu
@ 2021-03-08 16:34   ` Peter Maydell
  1 sibling, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2021-03-08 16:34 UTC (permalink / raw)
  To: Eric Auger
  Cc: Jean-Philippe Brucker, Jason Wang, QEMU Developers, Peter Xu,
	vivek.gautam, qemu-arm, Shameerali Kolothum Thodi, Paolo Bonzini,
	Eric Auger

On Thu, 25 Feb 2021 at 09:15, Eric Auger <eric.auger@redhat.com> wrote:
>
> Currently get_naturally_aligned_size() is used by the intel iommu
> to compute the maximum invalidation range based on @size which is
> a power of 2 while being aligned with the @start address and less
> than the maximum range defined by @gaw.
>
> This helper is also useful for other iommu devices (virtio-iommu,
> SMMUv3) to make sure IOMMU UNMAP notifiers only are called with
> power of 2 range sizes.
>
> Let's move this latter into dma-helpers.c and rename it into
> dma_aligned_pow2_mask(). Also rewrite the helper so that it
> accomodates UINT64_MAX values for the size mask and max mask.
> It now returns a mask instead of a size. Change the caller.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
> index a052f7bca3..2acb303be2 100644
> --- a/include/sysemu/dma.h
> +++ b/include/sysemu/dma.h
> @@ -296,4 +296,7 @@ uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
>  void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie,
>                      QEMUSGList *sg, enum BlockAcctType type);
>
> +uint64_t dma_aligned_pow2_mask(uint64_t start, uint64_t end,
> +                               int max_addr_bits);

All new globally-visible functions in header files should have
a doc-comment describing what they do, please.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 4/7] hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set
  2021-02-25  9:14 ` [PATCH v2 4/7] hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set Eric Auger
@ 2021-03-08 16:37   ` Peter Maydell
  2021-03-09  8:37     ` Auger Eric
  0 siblings, 1 reply; 19+ messages in thread
From: Peter Maydell @ 2021-03-08 16:37 UTC (permalink / raw)
  To: Eric Auger
  Cc: Jean-Philippe Brucker, Jason Wang, QEMU Developers, Peter Xu,
	vivek.gautam, qemu-arm, Shameerali Kolothum Thodi, Paolo Bonzini,
	Eric Auger

On Thu, 25 Feb 2021 at 09:15, Eric Auger <eric.auger@redhat.com> wrote:
>
> If the asid is not set, do not attempt to locate the key directly
> as all inserted keys have a valid asid.
>
> Use g_hash_table_foreach_remove instead.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  hw/arm/smmu-common.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
> index 405d5c5325..e9ca3aebb2 100644
> --- a/hw/arm/smmu-common.c
> +++ b/hw/arm/smmu-common.c
> @@ -151,7 +151,7 @@ inline void
>  smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
>                      uint8_t tg, uint64_t num_pages, uint8_t ttl)
>  {
> -    if (ttl && (num_pages == 1)) {
> +    if (ttl && (num_pages == 1) && (asid >= 0)) {
>          SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
>
>          g_hash_table_remove(s->iotlb, &key);

Do we also need to avoid the remove-by-key codepath if
the tg is not set ?

thanks
-- PMM


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 6/7] hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling
  2021-02-25  9:14 ` [PATCH v2 6/7] hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling Eric Auger
@ 2021-03-08 16:41   ` Peter Maydell
  0 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2021-03-08 16:41 UTC (permalink / raw)
  To: Eric Auger
  Cc: Jean-Philippe Brucker, Jason Wang, QEMU Developers, Peter Xu,
	vivek.gautam, qemu-arm, Shameerali Kolothum Thodi, Paolo Bonzini,
	Eric Auger

On Thu, 25 Feb 2021 at 09:15, Eric Auger <eric.auger@redhat.com> wrote:
>
> If the whole SID range (32b) is invalidated (SMMU_CMD_CFGI_ALL),
> @end overflows and we fail to handle the command properly.
>
> Once this gets fixed, the current code really is awkward in the
> sense it loops over the whole range instead of removing the
> currently cached configs through a hash table lookup.
>
> Fix both the overflow and the lookup.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 5/7] hw/arm/smmuv3: Enforce invalidation on a power of two range
  2021-02-25  9:14 ` [PATCH v2 5/7] hw/arm/smmuv3: Enforce invalidation on a power of two range Eric Auger
@ 2021-03-08 16:44   ` Peter Maydell
  0 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2021-03-08 16:44 UTC (permalink / raw)
  To: Eric Auger
  Cc: Jean-Philippe Brucker, Jason Wang, QEMU Developers, Peter Xu,
	vivek.gautam, qemu-arm, Shameerali Kolothum Thodi, Paolo Bonzini,
	Eric Auger

On Thu, 25 Feb 2021 at 09:15, Eric Auger <eric.auger@redhat.com> wrote:
>
> As of today, the driver can invalide a number of pages that is

"invalidate"

> not a power of 2. However IOTLB unmap notifications and internal
> IOTLB invalidations work with masks leading to erroneous
> invalidations.
>
> In case the range is not a power of 2, split invalidations into
> power of 2 invalidations.
>
> When looking for a single page entry in the vSMMU internal IOTLB,
> let's make sure that if the entry is not found using a
> g_hash_table_remove() we iterate over all the entries to find a
> potential range that overlaps it.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  hw/arm/smmu-common.c | 30 ++++++++++++++++++------------
>  hw/arm/smmuv3.c      | 24 ++++++++++++++++++++----
>  2 files changed, 38 insertions(+), 16 deletions(-)
>
> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
> index e9ca3aebb2..84d2c62c26 100644
> --- a/hw/arm/smmu-common.c
> +++ b/hw/arm/smmu-common.c
> @@ -151,22 +151,28 @@ inline void
>  smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
>                      uint8_t tg, uint64_t num_pages, uint8_t ttl)
>  {
> +    /* if tg is not set we use 4KB range invalidation */
> +    uint8_t granule = tg ? tg * 2 + 10 : 12;

I see this in-passing side-steps the question about how
we should be handling the lookup-by-key when the tg isn't set.

> +
>      if (ttl && (num_pages == 1) && (asid >= 0)) {
>          SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
>
> -        g_hash_table_remove(s->iotlb, &key);
> -    } else {
> -        /* if tg is not set we use 4KB range invalidation */
> -        uint8_t granule = tg ? tg * 2 + 10 : 12;
> -
> -        SMMUIOTLBPageInvInfo info = {
> -            .asid = asid, .iova = iova,
> -            .mask = (num_pages * 1 << granule) - 1};
> -
> -        g_hash_table_foreach_remove(s->iotlb,
> -                                    smmu_hash_remove_by_asid_iova,
> -                                    &info);
> +        if (g_hash_table_remove(s->iotlb, &key)) {
> +            return;
> +        }
> +        /*
> +         * if the entry is not found, let's see if it does not
> +         * belong to a larger IOTLB entry
> +         */
>      }
> +
> +    SMMUIOTLBPageInvInfo info = {
> +        .asid = asid, .iova = iova,
> +        .mask = (num_pages * 1 << granule) - 1};
> +
> +    g_hash_table_foreach_remove(s->iotlb,
> +                                smmu_hash_remove_by_asid_iova,
> +                                &info);
>  }
>
>  inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
> diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
> index bd1f97000d..fdd6332ce5 100644
> --- a/hw/arm/smmuv3.c
> +++ b/hw/arm/smmuv3.c
> @@ -861,7 +861,8 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
>      uint16_t vmid = CMD_VMID(cmd);
>      bool leaf = CMD_LEAF(cmd);
>      uint8_t tg = CMD_TG(cmd);
> -    hwaddr num_pages = 1;
> +    uint64_t first_page = 0, last_page;
> +    uint64_t num_pages = 1;
>      int asid = -1;
>
>      if (tg) {
> @@ -874,9 +875,24 @@ static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
>      if (type == SMMU_CMD_TLBI_NH_VA) {
>          asid = CMD_ASID(cmd);
>      }
> -    trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
> -    smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
> -    smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
> +
> +    /* Split invalidations into ^2 range invalidations */
> +    last_page = num_pages - 1;
> +    while (num_pages) {
> +        uint8_t granule = tg * 2 + 10;
> +        uint64_t mask, count;
> +
> +        mask = dma_aligned_pow2_mask(first_page, last_page, 64 - granule);
> +        count = mask + 1;
> +
> +        trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, count, ttl, leaf);
> +        smmuv3_inv_notifiers_iova(s, asid, addr, tg, count);
> +        smmu_iotlb_inv_iova(s, asid, addr, tg, count, ttl);
> +
> +        num_pages -= count;
> +        first_page += count;
> +        addr += count * BIT_ULL(granule);
> +    }
>  }

This is probably right but I'll wait to review it until I read
the doc comment for dma_aligned_pow2_mask().

-- PMM


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v2 4/7] hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set
  2021-03-08 16:37   ` Peter Maydell
@ 2021-03-09  8:37     ` Auger Eric
  0 siblings, 0 replies; 19+ messages in thread
From: Auger Eric @ 2021-03-09  8:37 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Jean-Philippe Brucker, Jason Wang, QEMU Developers, Peter Xu,
	vivek.gautam, qemu-arm, Shameerali Kolothum Thodi, Paolo Bonzini,
	Eric Auger

Hi Peter,
On 3/8/21 5:37 PM, Peter Maydell wrote:
> On Thu, 25 Feb 2021 at 09:15, Eric Auger <eric.auger@redhat.com> wrote:
>>
>> If the asid is not set, do not attempt to locate the key directly
>> as all inserted keys have a valid asid.
>>
>> Use g_hash_table_foreach_remove instead.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> ---
>>  hw/arm/smmu-common.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
>> index 405d5c5325..e9ca3aebb2 100644
>> --- a/hw/arm/smmu-common.c
>> +++ b/hw/arm/smmu-common.c
>> @@ -151,7 +151,7 @@ inline void
>>  smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
>>                      uint8_t tg, uint64_t num_pages, uint8_t ttl)
>>  {
>> -    if (ttl && (num_pages == 1)) {
>> +    if (ttl && (num_pages == 1) && (asid >= 0)) {
>>          SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
>>
>>          g_hash_table_remove(s->iotlb, &key);
> 
> Do we also need to avoid the remove-by-key codepath if
> the tg is not set ?
when TG is not set, TTL is res0 so I think it is safe.

Thanks

Eric
> 
> thanks
> -- PMM
> 



^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2021-03-09  8:38 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-25  9:14 [PATCH v2 0/7] Some vIOMMU fixes Eric Auger
2021-02-25  9:14 ` [PATCH v2 1/7] intel_iommu: Fix mask may be uninitialized in vtd_context_device_invalidate Eric Auger
2021-02-25 10:08   ` Philippe Mathieu-Daudé
2021-02-25 16:33     ` Auger Eric
2021-02-25 15:41   ` Peter Xu
2021-02-25  9:14 ` [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask() Eric Auger
2021-02-25 15:56   ` Peter Xu
2021-03-08 16:34   ` Peter Maydell
2021-02-25  9:14 ` [PATCH v2 3/7] virtio-iommu: Handle non power of 2 range invalidations Eric Auger
2021-02-25 16:01   ` Peter Xu
2021-02-25  9:14 ` [PATCH v2 4/7] hw/arm/smmu-common: Fix smmu_iotlb_inv_iova when asid is not set Eric Auger
2021-03-08 16:37   ` Peter Maydell
2021-03-09  8:37     ` Auger Eric
2021-02-25  9:14 ` [PATCH v2 5/7] hw/arm/smmuv3: Enforce invalidation on a power of two range Eric Auger
2021-03-08 16:44   ` Peter Maydell
2021-02-25  9:14 ` [PATCH v2 6/7] hw/arm/smmuv3: Fix SMMU_CMD_CFGI_STE_RANGE handling Eric Auger
2021-03-08 16:41   ` Peter Maydell
2021-02-25  9:14 ` [PATCH v2 7/7] hw/arm/smmuv3: Uniformize sid traces Eric Auger
2021-02-25 10:11   ` Philippe Mathieu-Daudé

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).