diff mbox series

[03/10] xen/arm: smmuv3: Ensure queue is read after updating prod pointer

Message ID b6051a32c515da23ed2d83467e43e59fd55127dc.1661331102.git.rahul.singh@arm.com (mailing list archive)
State Superseded
Headers show
Series xen/arm: smmuv3: Merge Linux fixes to Xen | expand

Commit Message

Rahul Singh Aug. 24, 2022, 1:53 p.m. UTC
Backport Linux commit a76a37777f2c936b1f046bfc0c5982c958b16bfe
"Ensure queue is read after updating prod pointer"

Original commit message:
    iommu/arm-smmu-v3: Ensure queue is read after updating prod pointer
    Reading the 'prod' MMIO register in order to determine whether or
    not there is valid data beyond 'cons' for a given queue does not
    provide sufficient dependency ordering, as the resulting access is
    address dependent only on 'cons' and can therefore be speculated
    ahead of time, potentially allowing stale data to be read by the
    CPU.

    Use readl() instead of readl_relaxed() when updating the shadow copy
    of the 'prod' pointer, so that all speculated memory reads from the
    corresponding queue can occur only from valid slots.

    Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
    Link: https://lore.kernel.org/r/1601281922-117296-1-git-send-email-wangzhou1@hisilicon.com
    [will: Use readl() instead of explicit barrier. Update 'cons' side to match.]
    Signed-off-by: Will Deacon <will@kernel.org>

Signed-off-by: Rahul Singh <rahul.singh@arm.com>
---
 xen/drivers/passthrough/arm/smmu-v3.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/xen/drivers/passthrough/arm/smmu-v3.c b/xen/drivers/passthrough/arm/smmu-v3.c
index 64d39bb4d3..93891a0704 100644
--- a/xen/drivers/passthrough/arm/smmu-v3.c
+++ b/xen/drivers/passthrough/arm/smmu-v3.c
@@ -963,8 +963,15 @@  static void queue_inc_cons(struct arm_smmu_ll_queue *q)
 
 static int queue_sync_prod_in(struct arm_smmu_queue *q)
 {
+	u32 prod;
 	int ret = 0;
-	u32 prod = readl_relaxed(q->prod_reg);
+
+	/*
+	 * We can't use the _relaxed() variant here, as we must prevent
+	 * speculative reads of the queue before we have determined that
+	 * prod has indeed moved.
+	 */
+	prod = readl(q->prod_reg);
 
 	if (Q_OVF(prod) != Q_OVF(q->llq.prod))
 		ret = -EOVERFLOW;