• James Hogan's avatar
    MIPS: SMP: Clear ASID without confusing has_valid_asid() · a05c3920
    James Hogan authored
    The SMP flush_tlb_*() functions may clear the memory map's ASIDs for
    other CPUs if the mm has only a single user (the current CPU) in order
    to avoid SMP calls. However this makes it appear to has_valid_asid(),
    which is used by various cache flush functions, as if the CPUs have
    never run in the mm, and therefore can't have cached any of its memory.
    
    For flush_tlb_mm() this doesn't sound unreasonable.
    
    flush_tlb_range() corresponds to flush_cache_range() which does do full
    indexed cache flushes, but only on the icache if the specified mapping
    is executable, otherwise it doesn't guarantee that there are no cache
    contents left for the mm.
    
    flush_tlb_page() corresponds to flush_cache_page(), which will perform
    address based cache ops on the specified page only, and also only
    touches the icache if the page is executable. It does not guarantee that
    there are no cache contents left for the mm.
    
    For example, this affects flush_cache_range() which uses the
    has_valid_asid() optimisation. It is required to flush the icache when
    mappings are made executable (e.g. using mprotect) so they are
    immediately usable. If some code is changed to non executable in order
    to be modified then it will not be flushed from the icache during that
    time, but the ASID on other CPUs may still be cleared for TLB flushing.
    When the code is changed back to executable, flush_cache_range() will
    assume the code hasn't run on those other CPUs due to the zero ASID, and
    won't invalidate the icache on them.
    
    This is fixed by clearing the other CPUs ASIDs to 1 instead of 0 for the
    above two flush_tlb_*() functions when the corresponding cache flushes
    are likely to be incomplete (non executable range flush, or any page
    flush). This ASID appears valid to has_valid_asid(), but still triggers
    ASID regeneration due to the upper ASID version bits being 0, which is
    less than the minimum ASID version of 1 and so always treated as stale.
    Signed-off-by: default avatarJames Hogan <james.hogan@imgtec.com>
    Cc: Paul Burton <paul.burton@imgtec.com>
    Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
    Cc: linux-mips@linux-mips.org
    Patchwork: https://patchwork.linux-mips.org/patch/13795/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
    a05c3920
c-r4k.c 47.6 KB