162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * vineetg: May 2011: for Non-aliasing VIPT D-cache following can be NOPs 662306a36Sopenharmony_ci * -flush_cache_dup_mm (fork) 762306a36Sopenharmony_ci * -likewise for flush_cache_mm (exit/execve) 862306a36Sopenharmony_ci * -likewise for flush_cache_{range,page} (munmap, exit, COW-break) 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * vineetg: April 2008 1162306a36Sopenharmony_ci * -Added a critical CacheLine flush to copy_to_user_page( ) which 1262306a36Sopenharmony_ci * was causing gdbserver to not setup breakpoints consistently 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#ifndef _ASM_CACHEFLUSH_H 1662306a36Sopenharmony_ci#define _ASM_CACHEFLUSH_H 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/mm.h> 1962306a36Sopenharmony_ci#include <asm/shmparam.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_civoid flush_cache_all(void); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_civoid flush_icache_range(unsigned long kstart, unsigned long kend); 2462306a36Sopenharmony_civoid __sync_icache_dcache(phys_addr_t paddr, unsigned long vaddr, int len); 2562306a36Sopenharmony_civoid __inv_icache_pages(phys_addr_t paddr, unsigned long vaddr, unsigned nr); 2662306a36Sopenharmony_civoid __flush_dcache_pages(phys_addr_t paddr, unsigned long vaddr, unsigned nr); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_civoid flush_dcache_page(struct page *page); 3162306a36Sopenharmony_civoid flush_dcache_folio(struct folio *folio); 3262306a36Sopenharmony_ci#define flush_dcache_folio flush_dcache_folio 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_civoid dma_cache_wback_inv(phys_addr_t start, unsigned long sz); 3562306a36Sopenharmony_civoid dma_cache_inv(phys_addr_t start, unsigned long sz); 3662306a36Sopenharmony_civoid dma_cache_wback(phys_addr_t start, unsigned long sz); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define flush_dcache_mmap_lock(mapping) do { } while (0) 3962306a36Sopenharmony_ci#define flush_dcache_mmap_unlock(mapping) do { } while (0) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* TBD: optimize this */ 4262306a36Sopenharmony_ci#define flush_cache_vmap(start, end) flush_cache_all() 4362306a36Sopenharmony_ci#define flush_cache_vmap_early(start, end) do { } while (0) 4462306a36Sopenharmony_ci#define flush_cache_vunmap(start, end) flush_cache_all() 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#define flush_cache_dup_mm(mm) /* called on fork (VIVT only) */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#ifndef CONFIG_ARC_CACHE_VIPT_ALIASING 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define flush_cache_mm(mm) /* called on munmap/exit */ 5162306a36Sopenharmony_ci#define flush_cache_range(mm, u_vstart, u_vend) 5262306a36Sopenharmony_ci#define flush_cache_page(vma, u_vaddr, pfn) /* PF handling/COW-break */ 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#else /* VIPT aliasing dcache */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* To clear out stale userspace mappings */ 5762306a36Sopenharmony_civoid flush_cache_mm(struct mm_struct *mm); 5862306a36Sopenharmony_civoid flush_cache_range(struct vm_area_struct *vma, 5962306a36Sopenharmony_ci unsigned long start,unsigned long end); 6062306a36Sopenharmony_civoid flush_cache_page(struct vm_area_struct *vma, 6162306a36Sopenharmony_ci unsigned long user_addr, unsigned long page); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* 6462306a36Sopenharmony_ci * To make sure that userspace mapping is flushed to memory before 6562306a36Sopenharmony_ci * get_user_pages() uses a kernel mapping to access the page 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_ci#define ARCH_HAS_FLUSH_ANON_PAGE 6862306a36Sopenharmony_civoid flush_anon_page(struct vm_area_struct *vma, 6962306a36Sopenharmony_ci struct page *page, unsigned long u_vaddr); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci#endif /* CONFIG_ARC_CACHE_VIPT_ALIASING */ 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* 7462306a36Sopenharmony_ci * A new pagecache page has PG_arch_1 clear - thus dcache dirty by default 7562306a36Sopenharmony_ci * This works around some PIO based drivers which don't call flush_dcache_page 7662306a36Sopenharmony_ci * to record that they dirtied the dcache 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_ci#define PG_dc_clean PG_arch_1 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define CACHE_COLORS_NUM 4 8162306a36Sopenharmony_ci#define CACHE_COLORS_MSK (CACHE_COLORS_NUM - 1) 8262306a36Sopenharmony_ci#define CACHE_COLOR(addr) (((unsigned long)(addr) >> (PAGE_SHIFT)) & CACHE_COLORS_MSK) 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* 8562306a36Sopenharmony_ci * Simple wrapper over config option 8662306a36Sopenharmony_ci * Bootup code ensures that hardware matches kernel configuration 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_cistatic inline int cache_is_vipt_aliasing(void) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci return IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* 9462306a36Sopenharmony_ci * checks if two addresses (after page aligning) index into same cache set 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ci#define addr_not_cache_congruent(addr1, addr2) \ 9762306a36Sopenharmony_ci({ \ 9862306a36Sopenharmony_ci cache_is_vipt_aliasing() ? \ 9962306a36Sopenharmony_ci (CACHE_COLOR(addr1) != CACHE_COLOR(addr2)) : 0; \ 10062306a36Sopenharmony_ci}) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ 10362306a36Sopenharmony_cido { \ 10462306a36Sopenharmony_ci memcpy(dst, src, len); \ 10562306a36Sopenharmony_ci if (vma->vm_flags & VM_EXEC) \ 10662306a36Sopenharmony_ci __sync_icache_dcache((unsigned long)(dst), vaddr, len); \ 10762306a36Sopenharmony_ci} while (0) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ 11062306a36Sopenharmony_ci memcpy(dst, src, len); \ 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#endif 113