e2aa0c3f8b
Refreshed all patches Dropped upstreamed patches: 522-PCI-aardvark-fix-logic-in-PCI-configuration-read-write-functions.patch 523-PCI-aardvark-set-PIO_ADDR_LS-correctly-in-advk_pcie_rd_conf.patch 525-PCI-aardvark-use-isr1-instead-of-isr0-interrupt-in-legacy-irq-mode.patch 527-PCI-aardvark-fix-PCIe-max-read-request-size-setting.patch updated patches: 524-PCI-aardvark-set-host-and-device-to-the-same-MAX-payload-size.patch 030-USB-serial-option-fix-dwm-158-3g-modem-interface.patch Added new ARM64 symbol: CONFIG_ARM64_ERRATUM_1024718 Compile-tested on: cns3xxx, imx6, mvebu (arm64), x86_64 Runtime-tested on: cns3xxx, imx6, x86_64 Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
90 lines
3.5 KiB
Diff
90 lines
3.5 KiB
Diff
From patchwork Thu Apr 26 23:28:34 2018
|
|
Content-Type: text/plain; charset="utf-8"
|
|
MIME-Version: 1.0
|
|
Content-Transfer-Encoding: 7bit
|
|
Subject: [v2] MIPS: c-r4k: fix data corruption related to cache coherence.
|
|
X-Patchwork-Submitter: NeilBrown <neil@brown.name>
|
|
X-Patchwork-Id: 19259
|
|
Message-Id: <87vacdlf8d.fsf@notabene.neil.brown.name>
|
|
To: James Hogan <jhogan@kernel.org>
|
|
Cc: Ralf Baechle <ralf@linux-mips.org>,
|
|
Paul Burton <paul.burton@mips.com>, linux-mips@linux-mips.org,
|
|
linux-kernel@vger.kernel.org
|
|
Date: Fri, 27 Apr 2018 09:28:34 +1000
|
|
From: NeilBrown <neil@brown.name>
|
|
List-Id: linux-mips <linux-mips.eddie.linux-mips.org>
|
|
|
|
When DMA will be performed to a MIPS32 1004K CPS, the
|
|
L1-cache for the range needs to be flushed and invalidated
|
|
first.
|
|
The code currently takes one of two approaches.
|
|
1/ If the range is less than the size of the dcache, then
|
|
HIT type requests flush/invalidate cache lines for the
|
|
particular addresses. HIT-type requests a globalised
|
|
by the CPS so this is safe on SMP.
|
|
|
|
2/ If the range is larger than the size of dcache, then
|
|
INDEX type requests flush/invalidate the whole cache.
|
|
INDEX type requests affect the local cache only. CPS
|
|
does not propagate them in any way. So this invalidation
|
|
is not safe on SMP CPS systems.
|
|
|
|
Data corruption due to '2' can quite easily be demonstrated by
|
|
repeatedly "echo 3 > /proc/sys/vm/drop_caches" and then sha1sum
|
|
a file that is several times the size of available memory.
|
|
Dropping caches means that large contiguous extents (large than
|
|
dcache) are more likely.
|
|
|
|
This was not a problem before Linux-4.8 because option 2 was
|
|
never used if CONFIG_MIPS_CPS was defined. The commit
|
|
which removed that apparently didn't appreciate the full
|
|
consequence of the change.
|
|
|
|
We could, in theory, globalize the INDEX based flush by sending an IPI
|
|
to other cores. These cache invalidation routines can be called with
|
|
interrupts disabled and synchronous IPI require interrupts to be
|
|
enabled. Asynchronous IPI may not trigger writeback soon enough.
|
|
So we cannot use IPI in practice.
|
|
|
|
We can already test is IPI would be needed for an INDEX operation
|
|
with r4k_op_needs_ipi(R4K_INDEX). If this is True then we mustn't try
|
|
the INDEX approach as we cannot use IPI. If this is False (e.g. when
|
|
there is only one core and hence one L1 cache) then it is safe to
|
|
use the INDEX approach without IPI.
|
|
|
|
This patch avoids options 2 if r4k_op_needs_ipi(R4K_INDEX), and so
|
|
eliminates the corruption.
|
|
|
|
Fixes: c00ab4896ed5 ("MIPS: Remove cpu_has_safe_index_cacheops")
|
|
Cc: stable@vger.kernel.org # v4.8+
|
|
Signed-off-by: NeilBrown <neil@brown.name>
|
|
---
|
|
arch/mips/mm/c-r4k.c | 9 ++++++---
|
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
|
|
|
--- a/arch/mips/mm/c-r4k.c
|
|
+++ b/arch/mips/mm/c-r4k.c
|
|
@@ -851,9 +851,12 @@ static void r4k_dma_cache_wback_inv(unsi
|
|
/*
|
|
* Either no secondary cache or the available caches don't have the
|
|
* subset property so we have to flush the primary caches
|
|
- * explicitly
|
|
+ * explicitly.
|
|
+ * If we would need IPI to perform an INDEX-type operation, then
|
|
+ * we have to use the HIT-type alternative as IPI cannot be used
|
|
+ * here due to interrupts possibly being disabled.
|
|
*/
|
|
- if (size >= dcache_size) {
|
|
+ if (!r4k_op_needs_ipi(R4K_INDEX) && size >= dcache_size) {
|
|
r4k_blast_dcache();
|
|
} else {
|
|
R4600_HIT_CACHEOP_WAR_IMPL;
|
|
@@ -890,7 +893,7 @@ static void r4k_dma_cache_inv(unsigned l
|
|
return;
|
|
}
|
|
|
|
- if (size >= dcache_size) {
|
|
+ if (!r4k_op_needs_ipi(R4K_INDEX) && size >= dcache_size) {
|
|
r4k_blast_dcache();
|
|
} else {
|
|
R4600_HIT_CACHEOP_WAR_IMPL;
|