162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
362306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
462306a36Sopenharmony_ci * for more details.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 by Ralf Baechle
762306a36Sopenharmony_ci * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#ifndef _ASM_CACHEFLUSH_H
1062306a36Sopenharmony_ci#define _ASM_CACHEFLUSH_H
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/* Keep includes the same across arches.  */
1362306a36Sopenharmony_ci#include <linux/mm.h>
1462306a36Sopenharmony_ci#include <asm/cpu-features.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* Cache flushing:
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci *  - flush_cache_all() flushes entire cache
1962306a36Sopenharmony_ci *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
2062306a36Sopenharmony_ci *  - flush_cache_dup mm(mm) handles cache flushing when forking
2162306a36Sopenharmony_ci *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
2262306a36Sopenharmony_ci *  - flush_cache_range(vma, start, end) flushes a range of pages
2362306a36Sopenharmony_ci *  - flush_icache_range(start, end) flush a range of instructions
2462306a36Sopenharmony_ci *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * MIPS specific flush operations:
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci *  - flush_icache_all() flush the entire instruction cache
2962306a36Sopenharmony_ci *  - flush_data_cache_page() flushes a page from the data cache
3062306a36Sopenharmony_ci *  - __flush_icache_user_range(start, end) flushes range of user instructions
3162306a36Sopenharmony_ci */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci /*
3462306a36Sopenharmony_ci * This flag is used to indicate that the page pointed to by a pte
3562306a36Sopenharmony_ci * is dirty and requires cleaning before returning it to the user.
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_ci#define PG_dcache_dirty			PG_arch_1
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define folio_test_dcache_dirty(folio)		\
4062306a36Sopenharmony_ci	test_bit(PG_dcache_dirty, &(folio)->flags)
4162306a36Sopenharmony_ci#define folio_set_dcache_dirty(folio)	\
4262306a36Sopenharmony_ci	set_bit(PG_dcache_dirty, &(folio)->flags)
4362306a36Sopenharmony_ci#define folio_clear_dcache_dirty(folio)	\
4462306a36Sopenharmony_ci	clear_bit(PG_dcache_dirty, &(folio)->flags)
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ciextern void (*flush_cache_all)(void);
4762306a36Sopenharmony_ciextern void (*__flush_cache_all)(void);
4862306a36Sopenharmony_ciextern void (*flush_cache_mm)(struct mm_struct *mm);
4962306a36Sopenharmony_ci#define flush_cache_dup_mm(mm)	do { (void) (mm); } while (0)
5062306a36Sopenharmony_ciextern void (*flush_cache_range)(struct vm_area_struct *vma,
5162306a36Sopenharmony_ci	unsigned long start, unsigned long end);
5262306a36Sopenharmony_ciextern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
5362306a36Sopenharmony_ciextern void __flush_dcache_pages(struct page *page, unsigned int nr);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
5662306a36Sopenharmony_cistatic inline void flush_dcache_folio(struct folio *folio)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	if (cpu_has_dc_aliases)
5962306a36Sopenharmony_ci		__flush_dcache_pages(&folio->page, folio_nr_pages(folio));
6062306a36Sopenharmony_ci	else if (!cpu_has_ic_fills_f_dc)
6162306a36Sopenharmony_ci		folio_set_dcache_dirty(folio);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci#define flush_dcache_folio flush_dcache_folio
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic inline void flush_dcache_page(struct page *page)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	if (cpu_has_dc_aliases)
6862306a36Sopenharmony_ci		__flush_dcache_pages(page, 1);
6962306a36Sopenharmony_ci	else if (!cpu_has_ic_fills_f_dc)
7062306a36Sopenharmony_ci		folio_set_dcache_dirty(page_folio(page));
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define flush_dcache_mmap_lock(mapping)		do { } while (0)
7462306a36Sopenharmony_ci#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define ARCH_HAS_FLUSH_ANON_PAGE
7762306a36Sopenharmony_ciextern void __flush_anon_page(struct page *, unsigned long);
7862306a36Sopenharmony_cistatic inline void flush_anon_page(struct vm_area_struct *vma,
7962306a36Sopenharmony_ci	struct page *page, unsigned long vmaddr)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	if (cpu_has_dc_aliases && PageAnon(page))
8262306a36Sopenharmony_ci		__flush_anon_page(page, vmaddr);
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ciextern void (*flush_icache_range)(unsigned long start, unsigned long end);
8662306a36Sopenharmony_ciextern void (*local_flush_icache_range)(unsigned long start, unsigned long end);
8762306a36Sopenharmony_ciextern void (*__flush_icache_user_range)(unsigned long start,
8862306a36Sopenharmony_ci					 unsigned long end);
8962306a36Sopenharmony_ciextern void (*__local_flush_icache_user_range)(unsigned long start,
9062306a36Sopenharmony_ci					       unsigned long end);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ciextern void (*__flush_cache_vmap)(void);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic inline void flush_cache_vmap(unsigned long start, unsigned long end)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	if (cpu_has_dc_aliases)
9762306a36Sopenharmony_ci		__flush_cache_vmap();
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define flush_cache_vmap_early(start, end)     do { } while (0)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciextern void (*__flush_cache_vunmap)(void);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic inline void flush_cache_vunmap(unsigned long start, unsigned long end)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	if (cpu_has_dc_aliases)
10762306a36Sopenharmony_ci		__flush_cache_vunmap();
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ciextern void copy_to_user_page(struct vm_area_struct *vma,
11162306a36Sopenharmony_ci	struct page *page, unsigned long vaddr, void *dst, const void *src,
11262306a36Sopenharmony_ci	unsigned long len);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ciextern void copy_from_user_page(struct vm_area_struct *vma,
11562306a36Sopenharmony_ci	struct page *page, unsigned long vaddr, void *dst, const void *src,
11662306a36Sopenharmony_ci	unsigned long len);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ciextern void (*flush_icache_all)(void);
11962306a36Sopenharmony_ciextern void (*flush_data_cache_page)(unsigned long addr);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/* Run kernel code uncached, useful for cache probing functions. */
12262306a36Sopenharmony_ciunsigned long run_uncached(void *func);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ciextern void *kmap_coherent(struct page *page, unsigned long addr);
12562306a36Sopenharmony_ciextern void kunmap_coherent(void);
12662306a36Sopenharmony_ciextern void *kmap_noncoherent(struct page *page, unsigned long addr);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic inline void kunmap_noncoherent(void)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	kunmap_coherent();
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#define ARCH_IMPLEMENTS_FLUSH_KERNEL_VMAP_RANGE 1
13462306a36Sopenharmony_ci/*
13562306a36Sopenharmony_ci * For now flush_kernel_vmap_range and invalidate_kernel_vmap_range both do a
13662306a36Sopenharmony_ci * cache writeback and invalidate operation.
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_ciextern void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic inline void flush_kernel_vmap_range(void *vaddr, int size)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	if (cpu_has_dc_aliases)
14362306a36Sopenharmony_ci		__flush_kernel_vmap_range((unsigned long) vaddr, size);
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic inline void invalidate_kernel_vmap_range(void *vaddr, int size)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	if (cpu_has_dc_aliases)
14962306a36Sopenharmony_ci		__flush_kernel_vmap_range((unsigned long) vaddr, size);
15062306a36Sopenharmony_ci}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci#endif /* _ASM_CACHEFLUSH_H */
153