123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- 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 <[email protected]>
- X-Patchwork-Id: 19259
- Message-Id: <[email protected]>
- To: James Hogan <[email protected]>
- Cc: Ralf Baechle <[email protected]>,
- Paul Burton <[email protected]>, [email protected],
- [email protected]
- Date: Fri, 27 Apr 2018 09:28:34 +1000
- From: NeilBrown <[email protected]>
- 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: [email protected] # v4.8+
- Signed-off-by: NeilBrown <[email protected]>
- ---
- 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;
|