• Ralf Baechle's avatar
    [MIPS] MT: Fix bug in multithreaded kernels. · a76ab5c1
    Ralf Baechle authored
    When GDB writes a breakpoint into address area of inferior process the
    kernel needs to invalidate the modified memory in the inferior which
    is done by calling flush_cache_page which in turns calls
    r4k_flush_cache_page and local_r4k_flush_cache_page for VSMP or SMTC
    kernel via r4k_on_each_cpu().
    
    As the VSMP and SMTC SMP kernels for 34K are running on a single shared
    caches it is possible to get away without interprocessor function calls.
    This optimization is implemented in r4k_on_each_cpu, so
    local_r4k_flush_cache_page is only ever called on the local CPU.
    
    This is where the following code in local_r4k_flush_cache_page() strikes:
    
            /*
             * If ownes no valid ASID yet, cannot possibly have gotten
             * this page into the cache.
             */
            if (cpu_context(smp_processor_id(), mm) == 0)
                    return;
    
    On VSMP and SMTC had a function of cpu_context() for each CPU(TC).
    
    So in case another CPU than the CPU executing local_r4k_cache_flush_page
    has not accessed the mm but one of the other CPUs has there may be data
    to be flushed in the cache yet local_r4k_cache_flush_page will falsely
    return leaving the I-cache inconsistent for the breakpoint.
    
    While the issue was discovered with GDB it also exists in
    local_r4k_flush_cache_range() and local_r4k_flush_cache().
    
    Fixed by introducing a new function has_valid_asid which on MT kernels
    returns true if a mm is active on any processor in the system.
    
    This is relativly expensive since for memory acccesses in that loop
    cache misses have to be assumed but it seems the most viable solution
    for 2.6.23 and older -stable kernels.
    Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
    a76ab5c1
c-r4k.c 33.7 KB