18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Based on arch/arm/mm/flush.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1995-2002 Russell King 68c2ecf20Sopenharmony_ci * Copyright (C) 2012 ARM Ltd. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/export.h> 108c2ecf20Sopenharmony_ci#include <linux/mm.h> 118c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <asm/cacheflush.h> 148c2ecf20Sopenharmony_ci#include <asm/cache.h> 158c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_civoid sync_icache_aliases(void *kaddr, unsigned long len) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci unsigned long addr = (unsigned long)kaddr; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci if (icache_is_aliasing()) { 228c2ecf20Sopenharmony_ci __clean_dcache_area_pou(kaddr, len); 238c2ecf20Sopenharmony_ci __flush_icache_all(); 248c2ecf20Sopenharmony_ci } else { 258c2ecf20Sopenharmony_ci /* 268c2ecf20Sopenharmony_ci * Don't issue kick_all_cpus_sync() after I-cache invalidation 278c2ecf20Sopenharmony_ci * for user mappings. 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ci __flush_icache_range(addr, addr + len); 308c2ecf20Sopenharmony_ci } 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, 348c2ecf20Sopenharmony_ci unsigned long uaddr, void *kaddr, 358c2ecf20Sopenharmony_ci unsigned long len) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci if (vma->vm_flags & VM_EXEC) 388c2ecf20Sopenharmony_ci sync_icache_aliases(kaddr, len); 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* 428c2ecf20Sopenharmony_ci * Copy user data from/to a page which is mapped into a different processes 438c2ecf20Sopenharmony_ci * address space. Really, we want to allow our "user space" model to handle 448c2ecf20Sopenharmony_ci * this. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_civoid copy_to_user_page(struct vm_area_struct *vma, struct page *page, 478c2ecf20Sopenharmony_ci unsigned long uaddr, void *dst, const void *src, 488c2ecf20Sopenharmony_ci unsigned long len) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci memcpy(dst, src, len); 518c2ecf20Sopenharmony_ci flush_ptrace_access(vma, page, uaddr, dst, len); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_civoid __sync_icache_dcache(pte_t pte) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci struct page *page = pte_page(pte); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (!test_bit(PG_dcache_clean, &page->flags)) { 598c2ecf20Sopenharmony_ci sync_icache_aliases(page_address(page), page_size(page)); 608c2ecf20Sopenharmony_ci set_bit(PG_dcache_clean, &page->flags); 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__sync_icache_dcache); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* 668c2ecf20Sopenharmony_ci * This function is called when a page has been modified by the kernel. Mark 678c2ecf20Sopenharmony_ci * it as dirty for later flushing when mapped in user space (if executable, 688c2ecf20Sopenharmony_ci * see __sync_icache_dcache). 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_civoid flush_dcache_page(struct page *page) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci if (test_bit(PG_dcache_clean, &page->flags)) 738c2ecf20Sopenharmony_ci clear_bit(PG_dcache_clean, &page->flags); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ciEXPORT_SYMBOL(flush_dcache_page); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* 788c2ecf20Sopenharmony_ci * Additional functions defined in assembly. 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__flush_icache_range); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#ifdef CONFIG_ARCH_HAS_PMEM_API 838c2ecf20Sopenharmony_civoid arch_wb_cache_pmem(void *addr, size_t size) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci /* Ensure order against any prior non-cacheable writes */ 868c2ecf20Sopenharmony_ci dmb(osh); 878c2ecf20Sopenharmony_ci __clean_dcache_area_pop(addr, size); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(arch_wb_cache_pmem); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_civoid arch_invalidate_pmem(void *addr, size_t size) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci __inval_dcache_area(addr, size); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(arch_invalidate_pmem); 968c2ecf20Sopenharmony_ci#endif 97