| // SPDX-License-Identifier: GPL-2.0 |
| // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. |
| |
| #include <linux/kernel.h> |
| #include <linux/mm.h> |
| #include <linux/fs.h> |
| #include <linux/pagemap.h> |
| #include <linux/syscalls.h> |
| #include <linux/spinlock.h> |
| #include <asm/page.h> |
| #include <asm/cache.h> |
| #include <asm/cacheflush.h> |
| #include <asm/cachectl.h> |
| #include <asm/tlbflush.h> |
| |
| #define PG_dcache_clean PG_arch_1 |
| |
| void flush_dcache_folio(struct folio *folio) |
| { |
| struct address_space *mapping; |
| |
| if (is_zero_pfn(folio_pfn(folio))) |
| return; |
| |
| mapping = folio_flush_mapping(folio); |
| |
| if (mapping && !folio_mapped(folio)) |
| clear_bit(PG_dcache_clean, &folio->flags); |
| else { |
| dcache_wbinv_all(); |
| if (mapping) |
| icache_inv_all(); |
| set_bit(PG_dcache_clean, &folio->flags); |
| } |
| } |
| EXPORT_SYMBOL(flush_dcache_folio); |
| |
| void flush_dcache_page(struct page *page) |
| { |
| flush_dcache_folio(page_folio(page)); |
| } |
| EXPORT_SYMBOL(flush_dcache_page); |
| |
| void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, |
| unsigned long addr, pte_t *ptep, unsigned int nr) |
| { |
| unsigned long pfn = pte_pfn(*ptep); |
| struct folio *folio; |
| |
| flush_tlb_page(vma, addr); |
| |
| if (!pfn_valid(pfn)) |
| return; |
| |
| if (is_zero_pfn(pfn)) |
| return; |
| |
| folio = page_folio(pfn_to_page(pfn)); |
| if (!test_and_set_bit(PG_dcache_clean, &folio->flags)) |
| dcache_wbinv_all(); |
| |
| if (folio_flush_mapping(folio)) { |
| if (vma->vm_flags & VM_EXEC) |
| icache_inv_all(); |
| } |
| } |
| |
| void flush_cache_range(struct vm_area_struct *vma, unsigned long start, |
| unsigned long end) |
| { |
| dcache_wbinv_all(); |
| |
| if (vma->vm_flags & VM_EXEC) |
| icache_inv_all(); |
| } |