162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Based on arch/arm/include/asm/cacheflush.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 1999-2002 Russell King.
662306a36Sopenharmony_ci * Copyright (C) 2012 ARM Ltd.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#ifndef __ASM_CACHEFLUSH_H
962306a36Sopenharmony_ci#define __ASM_CACHEFLUSH_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/kgdb.h>
1262306a36Sopenharmony_ci#include <linux/mm.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/*
1562306a36Sopenharmony_ci * This flag is used to indicate that the page pointed to by a pte is clean
1662306a36Sopenharmony_ci * and does not require cleaning before returning it to the user.
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ci#define PG_dcache_clean PG_arch_1
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/*
2162306a36Sopenharmony_ci *	MM Cache Management
2262306a36Sopenharmony_ci *	===================
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci *	The arch/arm64/mm/cache.S implements these methods.
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci *	Start addresses are inclusive and end addresses are exclusive; start
2762306a36Sopenharmony_ci *	addresses should be rounded down, end addresses up.
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci *	See Documentation/core-api/cachetlb.rst for more information. Please note that
3062306a36Sopenharmony_ci *	the implementation assumes non-aliasing VIPT D-cache and (aliasing)
3162306a36Sopenharmony_ci *	VIPT I-cache.
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci *	All functions below apply to the interval [start, end)
3462306a36Sopenharmony_ci *		- start  - virtual start address (inclusive)
3562306a36Sopenharmony_ci *		- end    - virtual end address (exclusive)
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci *	caches_clean_inval_pou(start, end)
3862306a36Sopenharmony_ci *
3962306a36Sopenharmony_ci *		Ensure coherency between the I-cache and the D-cache region to
4062306a36Sopenharmony_ci *		the Point of Unification.
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci *	caches_clean_inval_user_pou(start, end)
4362306a36Sopenharmony_ci *
4462306a36Sopenharmony_ci *		Ensure coherency between the I-cache and the D-cache region to
4562306a36Sopenharmony_ci *		the Point of Unification.
4662306a36Sopenharmony_ci *		Use only if the region might access user memory.
4762306a36Sopenharmony_ci *
4862306a36Sopenharmony_ci *	icache_inval_pou(start, end)
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci *		Invalidate I-cache region to the Point of Unification.
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci *	dcache_clean_inval_poc(start, end)
5362306a36Sopenharmony_ci *
5462306a36Sopenharmony_ci *		Clean and invalidate D-cache region to the Point of Coherency.
5562306a36Sopenharmony_ci *
5662306a36Sopenharmony_ci *	dcache_inval_poc(start, end)
5762306a36Sopenharmony_ci *
5862306a36Sopenharmony_ci *		Invalidate D-cache region to the Point of Coherency.
5962306a36Sopenharmony_ci *
6062306a36Sopenharmony_ci *	dcache_clean_poc(start, end)
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci *		Clean D-cache region to the Point of Coherency.
6362306a36Sopenharmony_ci *
6462306a36Sopenharmony_ci *	dcache_clean_pop(start, end)
6562306a36Sopenharmony_ci *
6662306a36Sopenharmony_ci *		Clean D-cache region to the Point of Persistence.
6762306a36Sopenharmony_ci *
6862306a36Sopenharmony_ci *	dcache_clean_pou(start, end)
6962306a36Sopenharmony_ci *
7062306a36Sopenharmony_ci *		Clean D-cache region to the Point of Unification.
7162306a36Sopenharmony_ci */
7262306a36Sopenharmony_ciextern void caches_clean_inval_pou(unsigned long start, unsigned long end);
7362306a36Sopenharmony_ciextern void icache_inval_pou(unsigned long start, unsigned long end);
7462306a36Sopenharmony_ciextern void dcache_clean_inval_poc(unsigned long start, unsigned long end);
7562306a36Sopenharmony_ciextern void dcache_inval_poc(unsigned long start, unsigned long end);
7662306a36Sopenharmony_ciextern void dcache_clean_poc(unsigned long start, unsigned long end);
7762306a36Sopenharmony_ciextern void dcache_clean_pop(unsigned long start, unsigned long end);
7862306a36Sopenharmony_ciextern void dcache_clean_pou(unsigned long start, unsigned long end);
7962306a36Sopenharmony_ciextern long caches_clean_inval_user_pou(unsigned long start, unsigned long end);
8062306a36Sopenharmony_ciextern void sync_icache_aliases(unsigned long start, unsigned long end);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic inline void flush_icache_range(unsigned long start, unsigned long end)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	caches_clean_inval_pou(start, end);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	/*
8762306a36Sopenharmony_ci	 * IPI all online CPUs so that they undergo a context synchronization
8862306a36Sopenharmony_ci	 * event and are forced to refetch the new instructions.
8962306a36Sopenharmony_ci	 */
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	/*
9262306a36Sopenharmony_ci	 * KGDB performs cache maintenance with interrupts disabled, so we
9362306a36Sopenharmony_ci	 * will deadlock trying to IPI the secondary CPUs. In theory, we can
9462306a36Sopenharmony_ci	 * set CACHE_FLUSH_IS_SAFE to 0 to avoid this known issue, but that
9562306a36Sopenharmony_ci	 * just means that KGDB will elide the maintenance altogether! As it
9662306a36Sopenharmony_ci	 * turns out, KGDB uses IPIs to round-up the secondary CPUs during
9762306a36Sopenharmony_ci	 * the patching operation, so we don't need extra IPIs here anyway.
9862306a36Sopenharmony_ci	 * In which case, add a KGDB-specific bodge and return early.
9962306a36Sopenharmony_ci	 */
10062306a36Sopenharmony_ci	if (in_dbg_master())
10162306a36Sopenharmony_ci		return;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	kick_all_cpus_sync();
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci#define flush_icache_range flush_icache_range
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci/*
10862306a36Sopenharmony_ci * Copy user data from/to a page which is mapped into a different
10962306a36Sopenharmony_ci * processes address space.  Really, we want to allow our "user
11062306a36Sopenharmony_ci * space" model to handle this.
11162306a36Sopenharmony_ci */
11262306a36Sopenharmony_ciextern void copy_to_user_page(struct vm_area_struct *, struct page *,
11362306a36Sopenharmony_ci	unsigned long, void *, const void *, unsigned long);
11462306a36Sopenharmony_ci#define copy_to_user_page copy_to_user_page
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/*
11762306a36Sopenharmony_ci * flush_dcache_folio is used when the kernel has written to the page
11862306a36Sopenharmony_ci * cache page at virtual address page->virtual.
11962306a36Sopenharmony_ci *
12062306a36Sopenharmony_ci * If this page isn't mapped (ie, page_mapping == NULL), or it might
12162306a36Sopenharmony_ci * have userspace mappings, then we _must_ always clean + invalidate
12262306a36Sopenharmony_ci * the dcache entries associated with the kernel mapping.
12362306a36Sopenharmony_ci *
12462306a36Sopenharmony_ci * Otherwise we can defer the operation, and clean the cache when we are
12562306a36Sopenharmony_ci * about to change to user space.  This is the same method as used on SPARC64.
12662306a36Sopenharmony_ci * See update_mmu_cache for the user space part.
12762306a36Sopenharmony_ci */
12862306a36Sopenharmony_ci#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
12962306a36Sopenharmony_ciextern void flush_dcache_page(struct page *);
13062306a36Sopenharmony_civoid flush_dcache_folio(struct folio *);
13162306a36Sopenharmony_ci#define flush_dcache_folio flush_dcache_folio
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic __always_inline void icache_inval_all_pou(void)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
13662306a36Sopenharmony_ci		return;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	asm("ic	ialluis");
13962306a36Sopenharmony_ci	dsb(ish);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci#include <asm-generic/cacheflush.h>
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci#endif /* __ASM_CACHEFLUSH_H */
145