flush_cache_mm = r3k_flush_cache_mm;
        flush_cache_range = r3k_flush_cache_range;
        flush_cache_page = r3k_flush_cache_page;
-       flush_icache_page = r3k_flush_icache_page;
+       __flush_icache_page = r3k_flush_icache_page;
        flush_icache_range = r3k_flush_icache_range;
 
        flush_cache_sigtramp = r3k_flush_cache_sigtramp;
 
        __flush_cache_all       = r4k___flush_cache_all;
        flush_cache_mm          = r4k_flush_cache_mm;
        flush_cache_page        = r4k_flush_cache_page;
-       flush_icache_page       = r4k_flush_icache_page;
+       __flush_icache_page     = r4k_flush_icache_page;
        flush_cache_range       = r4k_flush_cache_range;
 
        flush_cache_sigtramp    = r4k_flush_cache_sigtramp;
 
 
        /* These routines are for Icache coherence with the Dcache */
        flush_icache_range = sb1_flush_icache_range;
-       flush_icache_page = sb1_flush_icache_page;
+       __flush_icache_page = sb1_flush_icache_page;
        flush_icache_all = __sb1_flush_icache_all; /* local only */
 
        /* This implies an Icache flush too, so can't be nop'ed */
 
                flush_cache_mm          = (void *) tx39h_flush_icache_all;
                flush_cache_range       = (void *) tx39h_flush_icache_all;
                flush_cache_page        = (void *) tx39h_flush_icache_all;
-               flush_icache_page       = (void *) tx39h_flush_icache_all;
+               __flush_icache_page     = (void *) tx39h_flush_icache_all;
                flush_icache_range      = (void *) tx39h_flush_icache_all;
 
                flush_cache_sigtramp    = (void *) tx39h_flush_icache_all;
                flush_cache_mm = tx39_flush_cache_mm;
                flush_cache_range = tx39_flush_cache_range;
                flush_cache_page = tx39_flush_cache_page;
-               flush_icache_page = tx39_flush_icache_page;
+               __flush_icache_page = tx39_flush_icache_page;
                flush_icache_range = tx39_flush_icache_range;
 
                flush_cache_sigtramp = tx39_flush_cache_sigtramp;
 
 void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
        unsigned long pfn);
 void (*flush_icache_range)(unsigned long start, unsigned long end);
-void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
+void (*__flush_icache_page)(struct vm_area_struct *vma, struct page *page);
 
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
        struct address_space *mapping = page_mapping(page);
        unsigned long addr;
 
+       if (PageHighMem(page))
+               return;
        if (mapping && !mapping_mapped(mapping)) {
                SetPageDcacheDirty(page);
                return;
 {
        struct page *page;
        unsigned long pfn, addr;
+       int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
 
        pfn = pte_pfn(pte);
-       if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) &&
-           Page_dcache_dirty(page)) {
-               if (pages_do_alias((unsigned long)page_address(page),
-                                  address & PAGE_MASK)) {
-                       addr = (unsigned long) page_address(page);
+       if (unlikely(!pfn_valid(pfn)))
+               return;
+       page = pfn_to_page(pfn);
+       if (page_mapping(page) && Page_dcache_dirty(page)) {
+               addr = (unsigned long) page_address(page);
+               if (exec || pages_do_alias(addr, address & PAGE_MASK))
                        flush_data_cache_page(addr);
-               }
-
                ClearPageDcacheDirty(page);
        }
 }
 
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *  - flush_icache_range(start, end) flush a range of instructions
  *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
- *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
  *
  * MIPS specific flush operations:
  *
 
 static inline void flush_dcache_page(struct page *page)
 {
-       if (cpu_has_dc_aliases)
+       if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
                __flush_dcache_page(page);
 
 }
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-extern void (*flush_icache_page)(struct vm_area_struct *vma,
+extern void (*__flush_icache_page)(struct vm_area_struct *vma,
        struct page *page);
+static inline void flush_icache_page(struct vm_area_struct *vma,
+       struct page *page)
+{
+}
+
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
 #define flush_cache_vmap(start, end)           flush_cache_all()
 #define flush_cache_vunmap(start, end)         flush_cache_all()
        if (cpu_has_dc_aliases)
                flush_cache_page(vma, vaddr, page_to_pfn(page));
        memcpy(dst, src, len);
-       flush_icache_page(vma, page);
+       __flush_icache_page(vma, page);
 }
 
 static inline void copy_from_user_page(struct vm_area_struct *vma,
 
 
 #ifndef __ASSEMBLY__
 
+#include <asm/cpu-features.h>
+
 extern void clear_page(void * page);
 extern void copy_page(void * to, void * from);
 
        extern void (*flush_data_cache_page)(unsigned long addr);
 
        clear_page(addr);
-       if (pages_do_alias((unsigned long) addr, vaddr))
+       if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK))
                flush_data_cache_page((unsigned long)addr);
 }
 
        extern void (*flush_data_cache_page)(unsigned long addr);
 
        copy_page(vto, vfrom);
-       if (pages_do_alias((unsigned long)vto, vaddr))
+       if (!cpu_has_ic_fills_f_dc ||
+           pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
                flush_data_cache_page((unsigned long)vto);
 }