Commit:     2eaa7ec286db54cc1a864565ed9367966743bcbd
Parent:     eaf7943cc53d9688aa10267a226165356e956ec5
Author:     Ralf Baechle <[EMAIL PROTECTED]>
AuthorDate: Mon Feb 11 14:51:40 2008 +0000
Committer:  Ralf Baechle <[EMAIL PROTECTED]>
CommitDate: Tue Feb 19 17:01:31 2008 +0000

    [MIPS] Handle I-cache coherency in flush_cache_range()
    So far flush_cache_range() did't consider the I-cache largely because it
    did rarely ever matter to real world code.  This was working primarily
    because normally code and data are don't share the same pages - with the
    exception of MIPS16 code which uses address constants embedded between
    the code.   The following sequence of events may break the code:
     o MIPS16 executable being loaded
     o dynamic linker relocates the address constants embedded into the code:
     o   Uses mprotect(2) to make code pages PROT_READ|PROT_WRITE
     o   Performs the actual relocations by writing to the pages which likely
         are COW.  Because no PROT_EXEC is set I-cache coherence will not be
     o   Uses mprotect(2) to switch code pages back to PROT_READ|PROT_EXEC.
         This results in a call to flush_cache_range() which also does not
         consider I-caches.
     o => executing the page just having been relocated may now result in the
       I-cache getting refilled with stale data from memory.
    Signed-off-by: Ralf Baechle <[EMAIL PROTECTED]>
 arch/mips/mm/c-r4k.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 53ec052..2c4f7e1 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -364,20 +364,23 @@ static inline int has_valid_asid(const struct mm_struct 
 static inline void local_r4k_flush_cache_range(void * args)
        struct vm_area_struct *vma = args;
+       int exec = vma->vm_flags & VM_EXEC;
        if (!(has_valid_asid(vma->vm_mm)))
+       if (exec)
+               r4k_blast_icache();
 static void r4k_flush_cache_range(struct vm_area_struct *vma,
        unsigned long start, unsigned long end)
-       if (!cpu_has_dc_aliases)
-               return;
+       int exec = vma->vm_flags & VM_EXEC;
-       r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
+       if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
+               r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
 static inline void local_r4k_flush_cache_mm(void * args)
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to