[PATCH v4 4/7] firmware: samsung: acpm: Add memory barrier before advancing RX pointer
Tudor Ambarus
tudor.ambarus at linaro.org
Mon May 4 03:15:47 PDT 2026
Sashiko identified a silent data corruption in [1].
In acpm_get_rx(), the driver reads the response payload from SRAM using
__ioread32_copy() and subsequently updates the hardware RX rear pointer
via writel().
On weakly ordered architectures like ARM64, writel() provides a write
memory barrier (wmb()), which strictly orders prior writes against
subsequent writes. However, it does not order prior reads against
subsequent writes. Consequently, the CPU is permitted to reorder the
writel() store to become globally visible before the payload reads
have completed.
If this reordering occurs, the firmware may observe the updated rear
pointer, assume the queue slot is available, and overwrite the SRAM
payload while the kernel is still actively reading from it, leading
to silent data corruption.
Fix this by inserting a full memory barrier (mb()) before the writel()
to guarantee that all payload reads have completed before the hardware
queue pointer is advanced.
Cc: stable at vger.kernel.org
Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Closes: https://sashiko.dev/#/patchset/20260429-acpm-fixes-sashiko-reports-v3-0-47cf74ab09ad%40linaro.org
Signed-off-by: Tudor Ambarus <tudor.ambarus at linaro.org>
---
drivers/firmware/samsung/exynos-acpm.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index 9766425a44ab..a9449bc33bd0 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -5,6 +5,7 @@
* Copyright 2024 Linaro Ltd.
*/
+#include <asm/barrier.h>
#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/bits.h>
@@ -278,6 +279,9 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
i = (i + 1) % achan->qlen;
} while (i != rx_front);
+ /* Ensure all payload reads complete before advancing the rear pointer */
+ mb();
+
/* We saved all responses, mark RX empty. */
writel(rx_front, achan->rx.rear);
--
2.54.0.545.g6539524ca2-goog
More information about the linux-arm-kernel
mailing list