| // 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.f); | |
| else { | |
| dcache_wbinv_all(); | |
| if (mapping) | |
| icache_inv_all(); | |
| set_bit(PG_dcache_clean, &folio->flags.f); | |
| } | |
| } | |
| 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.f)) | |
| 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(); | |
| } |