1193240Ssam/* SPDX-License-Identifier: GPL-2.0-or-later */ 2193240Ssam/* 3193240Ssam */ 4193240Ssam#ifndef _ASM_POWERPC_CACHEFLUSH_H 5193240Ssam#define _ASM_POWERPC_CACHEFLUSH_H 6193240Ssam 7193240Ssam#include <linux/mm.h> 8193240Ssam#include <asm/cputable.h> 9193240Ssam#include <asm/cpu_has_feature.h> 10193240Ssam 11193240Ssam/* 12193240Ssam * This flag is used to indicate that the page pointed to by a pte is clean 13193240Ssam * and does not require cleaning before returning it to the user. 14193240Ssam */ 15193240Ssam#define PG_dcache_clean PG_arch_1 16193240Ssam 17193240Ssam#ifdef CONFIG_PPC_BOOK3S_64 18193240Ssam/* 19193240Ssam * Book3s has no ptesync after setting a pte, so without this ptesync it's 20193240Ssam * possible for a kernel virtual mapping access to return a spurious fault 21193240Ssam * if it's accessed right after the pte is set. The page fault handler does 22193240Ssam * not expect this type of fault. flush_cache_vmap is not exactly the right 23193240Ssam * place to put this, but it seems to work well enough. 24193240Ssam */ 25193240Ssamstatic inline void flush_cache_vmap(unsigned long start, unsigned long end) 26193240Ssam{ 27193240Ssam asm volatile("ptesync" ::: "memory"); 28193240Ssam} 29193240Ssam#define flush_cache_vmap flush_cache_vmap 30193240Ssam#endif /* CONFIG_PPC_BOOK3S_64 */ 31193240Ssam 32193240Ssam#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 33193240Ssam/* 34193240Ssam * This is called when a page has been modified by the kernel. 35193240Ssam * It just marks the page as not i-cache clean. We do the i-cache 36193240Ssam * flush later when the page is given to a user process, if necessary. 37193240Ssam */ 38193240Ssamstatic inline void flush_dcache_folio(struct folio *folio) 39193240Ssam{ 40193240Ssam if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) 41193240Ssam return; 42193240Ssam /* avoid an atomic op if possible */ 43193240Ssam if (test_bit(PG_dcache_clean, &folio->flags)) 44193240Ssam clear_bit(PG_dcache_clean, &folio->flags); 45193240Ssam} 46193240Ssam#define flush_dcache_folio flush_dcache_folio 47193240Ssam 48193240Ssamstatic inline void flush_dcache_page(struct page *page) 49193240Ssam{ 50193240Ssam flush_dcache_folio(page_folio(page)); 51193240Ssam} 52193240Ssam 53193240Ssamvoid flush_icache_range(unsigned long start, unsigned long stop); 54193240Ssam#define flush_icache_range flush_icache_range 55193240Ssam 56193240Ssamvoid flush_icache_user_page(struct vm_area_struct *vma, struct page *page, 57193240Ssam unsigned long addr, int len); 58193240Ssam#define flush_icache_user_page flush_icache_user_page 59193240Ssam 60193240Ssamvoid flush_dcache_icache_folio(struct folio *folio); 61193240Ssam 62193240Ssam/** 63193240Ssam * flush_dcache_range(): Write any modified data cache blocks out to memory and 64193240Ssam * invalidate them. Does not invalidate the corresponding instruction cache 65193240Ssam * blocks. 66193240Ssam * 67193240Ssam * @start: the start address 68193240Ssam * @stop: the stop address (exclusive) 69193240Ssam */ 70193240Ssamstatic inline void flush_dcache_range(unsigned long start, unsigned long stop) 71193240Ssam{ 72193240Ssam unsigned long shift = l1_dcache_shift(); 73193240Ssam unsigned long bytes = l1_dcache_bytes(); 74193240Ssam void *addr = (void *)(start & ~(bytes - 1)); 75193240Ssam unsigned long size = stop - (unsigned long)addr + (bytes - 1); 76193240Ssam unsigned long i; 77193240Ssam 78193240Ssam if (IS_ENABLED(CONFIG_PPC64)) 79193240Ssam mb(); /* sync */ 80193240Ssam 81193240Ssam for (i = 0; i < size >> shift; i++, addr += bytes) 82193240Ssam dcbf(addr); 83193240Ssam mb(); /* sync */ 84193240Ssam 85193240Ssam} 86195171Ssam 87193240Ssam/* 88193240Ssam * Write any modified data cache blocks out to memory. 89193240Ssam * Does not invalidate the corresponding cache lines (especially for 90193240Ssam * any corresponding instruction cache). 91193240Ssam */ 92193240Ssamstatic inline void clean_dcache_range(unsigned long start, unsigned long stop) 93193240Ssam{ 94193240Ssam unsigned long shift = l1_dcache_shift(); 95193240Ssam unsigned long bytes = l1_dcache_bytes(); 96193240Ssam void *addr = (void *)(start & ~(bytes - 1)); 97195171Ssam unsigned long size = stop - (unsigned long)addr + (bytes - 1); 98195171Ssam unsigned long i; 99193240Ssam 100193240Ssam for (i = 0; i < size >> shift; i++, addr += bytes) 101193240Ssam dcbst(addr); 102193240Ssam mb(); /* sync */ 103193240Ssam} 104195171Ssam 105195171Ssam/* 106193240Ssam * Like above, but invalidate the D-cache. This is used by the 8xx 107193240Ssam * to invalidate the cache so the PPC core doesn't get stale data 108193240Ssam * from the CPM (no cache snooping here :-). 109193240Ssam */ 110193240Ssamstatic inline void invalidate_dcache_range(unsigned long start, 111193240Ssam unsigned long stop) 112193240Ssam{ 113193240Ssam unsigned long shift = l1_dcache_shift(); 114193240Ssam unsigned long bytes = l1_dcache_bytes(); 115193240Ssam void *addr = (void *)(start & ~(bytes - 1)); 116193240Ssam unsigned long size = stop - (unsigned long)addr + (bytes - 1); 117193240Ssam unsigned long i; 118193240Ssam 119193240Ssam for (i = 0; i < size >> shift; i++, addr += bytes) 120193240Ssam dcbi(addr); 121193240Ssam mb(); /* sync */ 122193240Ssam} 123193240Ssam 124193240Ssam#ifdef CONFIG_4xx 125195171Ssamstatic inline void flush_instruction_cache(void) 126193240Ssam{ 127195171Ssam iccci((void *)KERNELBASE); 128195171Ssam isync(); 129193240Ssam} 130193240Ssam#else 131193240Ssamvoid flush_instruction_cache(void); 132193240Ssam#endif 133193240Ssam 134193240Ssam#include <asm-generic/cacheflush.h> 135193240Ssam 136193240Ssam#endif /* _ASM_POWERPC_CACHEFLUSH_H */ 137193240Ssam