From: Eric Auger <eric.auger@redhat.com>
To: eric.auger.pro@gmail.com, eric.auger@redhat.com,
qemu-devel@nongnu.org, qemu-arm@nongnu.org,
peter.maydell@linaro.org, jean-philippe@linaro.org,
peterx@redhat.com, jasowang@redhat.com, pbonzini@redhat.com
Cc: vivek.gautam@arm.com, shameerali.kolothum.thodi@huawei.com
Subject: [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask()
Date: Thu, 25 Feb 2021 10:14:30 +0100 [thread overview]
Message-ID: <20210225091435.644762-3-eric.auger@redhat.com> (raw)
In-Reply-To: <20210225091435.644762-1-eric.auger@redhat.com>
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
next prev parent reply other threads:[~2021-02-25 9:19 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Eric Auger [this message]
2021-02-25 15:56 ` [PATCH v2 2/7] dma: Introduce dma_aligned_pow2_mask() 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é
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210225091435.644762-3-eric.auger@redhat.com \
--to=eric.auger@redhat.com \
--cc=eric.auger.pro@gmail.com \
--cc=jasowang@redhat.com \
--cc=jean-philippe@linaro.org \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=peterx@redhat.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=shameerali.kolothum.thodi@huawei.com \
--cc=vivek.gautam@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).