--- zzzz-none-000/linux-3.10.107/arch/mips/mm/cache.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/arch/mips/mm/cache.c 2021-11-10 11:53:54.000000000 +0000 @@ -20,6 +20,8 @@ #include #include #include +#include +#include /* Cache operations. */ void (*flush_cache_all)(void); @@ -32,8 +34,8 @@ void (*flush_icache_range)(unsigned long start, unsigned long end); void (*local_flush_icache_range)(unsigned long start, unsigned long end); -void (*__flush_cache_vmap)(void); -void (*__flush_cache_vunmap)(void); +void (*__flush_cache_vmap)(unsigned long start, unsigned long end); +void (*__flush_cache_vunmap)(unsigned long start, unsigned long end); void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size); void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size); @@ -44,10 +46,13 @@ void (*flush_cache_sigtramp)(unsigned long addr); void (*local_flush_data_cache_page)(void * addr); void (*flush_data_cache_page)(unsigned long addr); +void (*mips_flush_data_cache_range)(struct vm_area_struct *vma, + struct page *page, unsigned long addr, unsigned long size); void (*flush_icache_all)(void); EXPORT_SYMBOL_GPL(local_flush_data_cache_page); EXPORT_SYMBOL(flush_data_cache_page); +EXPORT_SYMBOL(mips_flush_data_cache_range); EXPORT_SYMBOL(flush_icache_all); #ifdef CONFIG_DMA_NONCOHERENT @@ -58,6 +63,8 @@ void (*_dma_cache_inv)(unsigned long start, unsigned long size); EXPORT_SYMBOL(_dma_cache_wback_inv); +EXPORT_SYMBOL(_dma_cache_wback); +EXPORT_SYMBOL(_dma_cache_inv); #endif /* CONFIG_DMA_NONCOHERENT */ @@ -80,12 +87,9 @@ void __flush_dcache_page(struct page *page) { - struct address_space *mapping = page_mapping(page); - unsigned long addr; + void *addr; - if (PageHighMem(page)) - return; - if (mapping && !mapping_mapped(mapping)) { + if (page_mapping(page) && !page_mapped(page)) { SetPageDcacheDirty(page); return; } @@ -95,25 +99,55 @@ * case is for exec env/arg pages and those are %99 certainly going to * get faulted into the tlb (and thus flushed) anyways. */ - addr = (unsigned long) page_address(page); - flush_data_cache_page(addr); + if (PageHighMem(page)) { + addr = kmap_atomic(page); + flush_data_cache_page((unsigned long)addr); + kunmap_atomic(addr); + } else { + addr = (void *) page_address(page); + flush_data_cache_page((unsigned long)addr); + } + ClearPageDcacheDirty(page); } EXPORT_SYMBOL(__flush_dcache_page); void __flush_anon_page(struct page *page, unsigned long vmaddr) { - unsigned long addr = (unsigned long) page_address(page); + if (!PageHighMem(page)) { + unsigned long addr = (unsigned long) page_address(page); - if (pages_do_alias(addr, vmaddr)) { - if (page_mapped(page) && !Page_dcache_dirty(page)) { - void *kaddr; - - kaddr = kmap_coherent(page, vmaddr); - flush_data_cache_page((unsigned long)kaddr); - kunmap_coherent(); - } else - flush_data_cache_page(addr); + if (pages_do_alias(addr, vmaddr & PAGE_MASK)) { + if (page_mapped(page) && !Page_dcache_dirty(page)) { + void *kaddr; + + kaddr = kmap_coherent(page, vmaddr); + flush_data_cache_page((unsigned long)kaddr); + kunmap_coherent(); + } else { + flush_data_cache_page(addr); + ClearPageDcacheDirty(page); + } + } + } else { + void *laddr = lowmem_page_address(page); + + if (pages_do_alias((unsigned long)laddr, vmaddr & PAGE_MASK)) { + if (page_mapped(page) && !Page_dcache_dirty(page)) { + void *kaddr; + + kaddr = kmap_coherent(page, vmaddr); + flush_data_cache_page((unsigned long)kaddr); + kunmap_coherent(); + } else { + void *kaddr; + + kaddr = kmap_atomic(page); + flush_data_cache_page((unsigned long)kaddr); + kunmap_atomic(kaddr); + ClearPageDcacheDirty(page); + } + } } } @@ -127,15 +161,28 @@ int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc; pfn = pte_pfn(pte); - if (unlikely(!pfn_valid(pfn))) + if (unlikely(!pfn_valid(pfn))) { + wmb(); 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)) + if (page_mapped(page) && Page_dcache_dirty(page)) { + void *kaddr = NULL; + if (PageHighMem(page)) { + addr = (unsigned long)kmap_atomic(page); + kaddr = (void *)addr; + } else + addr = (unsigned long) page_address(page); + if (exec || (cpu_has_dc_aliases && + pages_do_alias(addr, address & PAGE_MASK))) { flush_data_cache_page(addr); - ClearPageDcacheDirty(page); + ClearPageDcacheDirty(page); + } + + if (kaddr) + kunmap_atomic((void *)kaddr); } + wmb(); /* finish any outstanding arch cache flushes before ret to user */ } unsigned long _page_cachable_default; @@ -184,10 +231,22 @@ void __cpuinit cpu_cache_init(void) { + avm_cache_set_coherency(); + if (cpu_has_3k_cache) { extern void __weak r3k_cache_init(void); +#ifdef CONFIG_MACH_FUSIV_MIPS1 + extern void ld_mmu_lx4189(void); + + if ((current_cpu_data.processor_id & 0xFFFF) == + PRID_IMP_FUSIV_MIPS1) + ld_mmu_lx4189(); + else + r3k_cache_init(); +#else r3k_cache_init(); +#endif } if (cpu_has_6k_cache) { extern void __weak r6k_cache_init(void);