• NeilBrown's avatar
    MIPS: c-r4k: Fix data corruption related to cache coherence · 55a2aa08
    NeilBrown authored
    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 if 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: c00ab489 ("MIPS: Remove cpu_has_safe_index_cacheops")
    Signed-off-by: default avatarNeilBrown <neil@brown.name>
    Cc: Ralf Baechle <ralf@linux-mips.org>
    Cc: Paul Burton <paul.burton@mips.com>
    Cc: linux-mips@linux-mips.org
    Cc: <stable@vger.kernel.org> # 4.8+
    Patchwork: https://patchwork.linux-mips.org/patch/19259/Signed-off-by: default avatarJames Hogan <jhogan@kernel.org>
    55a2aa08
c-r4k.c 53.4 KB