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