103-MIPS-c-r4k-fix-data-corruption-related-to-cache-coherence.patch 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. From patchwork Thu Apr 26 23:28:34 2018
  2. Content-Type: text/plain; charset="utf-8"
  3. MIME-Version: 1.0
  4. Content-Transfer-Encoding: 7bit
  5. Subject: [v2] MIPS: c-r4k: fix data corruption related to cache coherence.
  6. X-Patchwork-Submitter: NeilBrown <[email protected]>
  7. X-Patchwork-Id: 19259
  8. Message-Id: <[email protected]>
  9. To: James Hogan <[email protected]>
  10. Cc: Ralf Baechle <[email protected]>,
  11. Paul Burton <[email protected]>, [email protected],
  12. [email protected]
  13. Date: Fri, 27 Apr 2018 09:28:34 +1000
  14. From: NeilBrown <[email protected]>
  15. List-Id: linux-mips <linux-mips.eddie.linux-mips.org>
  16. When DMA will be performed to a MIPS32 1004K CPS, the
  17. L1-cache for the range needs to be flushed and invalidated
  18. first.
  19. The code currently takes one of two approaches.
  20. 1/ If the range is less than the size of the dcache, then
  21. HIT type requests flush/invalidate cache lines for the
  22. particular addresses. HIT-type requests a globalised
  23. by the CPS so this is safe on SMP.
  24. 2/ If the range is larger than the size of dcache, then
  25. INDEX type requests flush/invalidate the whole cache.
  26. INDEX type requests affect the local cache only. CPS
  27. does not propagate them in any way. So this invalidation
  28. is not safe on SMP CPS systems.
  29. Data corruption due to '2' can quite easily be demonstrated by
  30. repeatedly "echo 3 > /proc/sys/vm/drop_caches" and then sha1sum
  31. a file that is several times the size of available memory.
  32. Dropping caches means that large contiguous extents (large than
  33. dcache) are more likely.
  34. This was not a problem before Linux-4.8 because option 2 was
  35. never used if CONFIG_MIPS_CPS was defined. The commit
  36. which removed that apparently didn't appreciate the full
  37. consequence of the change.
  38. We could, in theory, globalize the INDEX based flush by sending an IPI
  39. to other cores. These cache invalidation routines can be called with
  40. interrupts disabled and synchronous IPI require interrupts to be
  41. enabled. Asynchronous IPI may not trigger writeback soon enough.
  42. So we cannot use IPI in practice.
  43. We can already test is IPI would be needed for an INDEX operation
  44. with r4k_op_needs_ipi(R4K_INDEX). If this is True then we mustn't try
  45. the INDEX approach as we cannot use IPI. If this is False (e.g. when
  46. there is only one core and hence one L1 cache) then it is safe to
  47. use the INDEX approach without IPI.
  48. This patch avoids options 2 if r4k_op_needs_ipi(R4K_INDEX), and so
  49. eliminates the corruption.
  50. Fixes: c00ab4896ed5 ("MIPS: Remove cpu_has_safe_index_cacheops")
  51. Cc: [email protected] # v4.8+
  52. Signed-off-by: NeilBrown <[email protected]>
  53. ---
  54. arch/mips/mm/c-r4k.c | 9 ++++++---
  55. 1 file changed, 6 insertions(+), 3 deletions(-)
  56. --- a/arch/mips/mm/c-r4k.c
  57. +++ b/arch/mips/mm/c-r4k.c
  58. @@ -851,9 +851,12 @@ static void r4k_dma_cache_wback_inv(unsi
  59. /*
  60. * Either no secondary cache or the available caches don't have the
  61. * subset property so we have to flush the primary caches
  62. - * explicitly
  63. + * explicitly.
  64. + * If we would need IPI to perform an INDEX-type operation, then
  65. + * we have to use the HIT-type alternative as IPI cannot be used
  66. + * here due to interrupts possibly being disabled.
  67. */
  68. - if (size >= dcache_size) {
  69. + if (!r4k_op_needs_ipi(R4K_INDEX) && size >= dcache_size) {
  70. r4k_blast_dcache();
  71. } else {
  72. R4600_HIT_CACHEOP_WAR_IMPL;
  73. @@ -890,7 +893,7 @@ static void r4k_dma_cache_inv(unsigned l
  74. return;
  75. }
  76. - if (size >= dcache_size) {
  77. + if (!r4k_op_needs_ipi(R4K_INDEX) && size >= dcache_size) {
  78. r4k_blast_dcache();
  79. } else {
  80. R4600_HIT_CACHEOP_WAR_IMPL;