From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C4D1144A739 for ; Wed, 17 Jun 2026 14:27:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781706466; cv=none; b=Ndo3Ou0HwyK2ekDKpCKF0BpZG0XSQG7dT2yziTM6b/Y5J/ulR98r48stCvEdXy4lwTMPq7E7SbZ1LvfXal1D2i2z4yK6LVV0SD96Rnmg3n2SIs8K0EPZBYJOgj2rLFM7NPS2Kh4F3CCSZbkNfs+n4X1S5QeFnLVxClXlhMp8ZM0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781706466; c=relaxed/simple; bh=aQktCdjb5lwGQvya00rvIWi+5TgRtsh4QwvjWuHC0SE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TOzLkPzEMVqIqaYsGQucm/6I7H2WIP0xgVF7mAdwzR5dd4EjNsyiYqkZHFTu26gv+HL0DBl/8tKHNSFhbOSQ45/3Fb4/Qf3WiQXlz2wMvZT8dhdXcdPWIENp1xjBdgS4B+tI/PgXfbDZ+cCmowesOohDsxeMLAAxh6Ttf6RCHZU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hDhgvxU/; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hDhgvxU/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 35F311F00A3D; Wed, 17 Jun 2026 14:27:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1781706464; bh=TbXoQinPA4I9fDQmqsTR0eDggoTGl5FrMCaKRpD+Wtg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=hDhgvxU/LS5Irc/LLWIUSLqTbUG8vyu/rt09tkXhh5Erxbv3qdTKvoVDHHTRvojV4 MvRSVfXEQlPFHkmNXI2iz+vxG3L396YltKZ6Z4Yw5Lf0EaIgZoTnBx4QlIdEH3wK45 sdnoySZk+8nYkKFJnje3Tbjk+aJJNyGBpCRMDwIBRPWVVN4f5dQdX7W9I4wCMlp2QB 7R7rypRyIU5gKUkVDOiGriJws9v7WS7QG1wuQDfCFapxgQUy9zXqWlpMOCSGsPj1cS JsO1W2F/uS9HFDXTXmTZAp1/dg0Ce0ezUAh02uohQSSZCmsJ33y9tsqQbzi7/Q9eMH miPuCStu2vNDQ== From: Sasha Levin To: stable@vger.kernel.org Cc: Tudor Ambarus , Krzysztof Kozlowski , Sasha Levin Subject: [PATCH 7.0.y 5/5] firmware: samsung: acpm: Fix missing LKMM barriers in sequence allocator Date: Wed, 17 Jun 2026 10:27:39 -0400 Message-ID: <20260617142739.3938338-5-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260617142739.3938338-1-sashal@kernel.org> References: <2026061551-lung-clutter-0849@gregkh> <20260617142739.3938338-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Tudor Ambarus [ Upstream commit bf296f83a3ddab1ab875edc4e8862cb10553064f ] Sashiko identified memory ordering races in [1]. The ACPM driver uses a globally shared 'bitmap_seqnum' to track available sequence numbers. Even though threads now strictly free their own sequence numbers, the allocation and freeing of these bits across concurrent threads are effectively lockless operations and require explicit LKMM memory barriers. Previously, the driver used plain bitwise operators (test_bit, set_bit, clear_bit), which lack ordering guarantees. This creates two race conditions on weakly ordered architectures like ARM64: 1. Polling Release Violation: The polling thread copies its payload and calls clear_bit(). Without a release barrier, the CPU can reorder the memory operations, making the cleared bit globally visible before the payload reads have fully completed. 2. TX Acquire Violation: The TX thread loops on test_bit(), calls set_bit(), and then wipes the payload buffer via memset(). Without an acquire barrier, the CPU can speculatively execute the memset() before the bit is safely and formally claimed. If these reorderings overlap, a new TX thread can claim the sequence number and overwrite the buffer while the original polling thread is still actively reading from it. Fix this by upgrading the bitwise operators. Wrap the TX allocation in test_and_set_bit_lock() to establish formal LKMM Acquire semantics, and pair it with clear_bit_unlock() in the polling path to enforce Release semantics. Cc: stable@vger.kernel.org Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver") Closes: https://sashiko.dev/#/patchset/20260423-acpm-fixes-sashiko-reports-v1-0-2217b790925e%40linaro.org [1] Signed-off-by: Tudor Ambarus Link: https://patch.msgid.link/20260505-acpm-fixes-sashiko-reports-v5-6-43b5ee7f1674@linaro.org Signed-off-by: Krzysztof Kozlowski Signed-off-by: Sasha Levin --- drivers/firmware/samsung/exynos-acpm.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c index 7eda1aff4c197b..c472569441949c 100644 --- a/drivers/firmware/samsung/exynos-acpm.c +++ b/drivers/firmware/samsung/exynos-acpm.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include @@ -340,7 +340,7 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan, acpm_get_saved_rx(achan, xfer, seqnum); /* Relinquish ownership of the sequence slot */ - clear_bit(seqnum - 1, achan->bitmap_seqnum); + clear_bit_unlock(seqnum - 1, achan->bitmap_seqnum); return 0; } @@ -397,11 +397,18 @@ static void acpm_prepare_xfer(struct acpm_chan *achan, struct acpm_rx_data *rx_data; u32 *txd = (u32 *)xfer->txd; - /* Prevent chan->seqnum from being re-used */ + /* + * Prevent chan->seqnum from being re-used. + * test_and_set_bit_lock() provides formal LKMM Acquire semantics. + * It pairs with the RX thread's clear_bit_unlock() to ensure the CPU + * does not speculatively execute the rx_data buffer wipe (memset) + * before the sequence number is safely claimed. + */ do { if (++achan->seqnum == ACPM_SEQNUM_MAX) achan->seqnum = 1; - } while (test_bit(achan->seqnum - 1, achan->bitmap_seqnum)); + /* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */ + } while (test_and_set_bit_lock(achan->seqnum - 1, achan->bitmap_seqnum)); txd[0] |= FIELD_PREP(ACPM_PROTOCOL_SEQNUM, achan->seqnum); @@ -411,9 +418,6 @@ static void acpm_prepare_xfer(struct acpm_chan *achan, memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd); /* zero means no response expected */ rx_data->rxcnt = xfer->rxcnt; - - /* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */ - set_bit(achan->seqnum - 1, achan->bitmap_seqnum); } /** -- 2.53.0