xref: /linux/arch/riscv/include/asm/cacheflush.h (revision 97d8894b6f4c44762fd48f5d29e73358d6181dbb)
150acfb2bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2fab957c1SPalmer Dabbelt /*
3fab957c1SPalmer Dabbelt  * Copyright (C) 2015 Regents of the University of California
4fab957c1SPalmer Dabbelt  */
5fab957c1SPalmer Dabbelt 
6fab957c1SPalmer Dabbelt #ifndef _ASM_RISCV_CACHEFLUSH_H
7fab957c1SPalmer Dabbelt #define _ASM_RISCV_CACHEFLUSH_H
8fab957c1SPalmer Dabbelt 
92d69fbf3SPaul Walmsley #include <linux/mm.h>
10fab957c1SPalmer Dabbelt 
11fab957c1SPalmer Dabbelt static inline void local_flush_icache_all(void)
12fab957c1SPalmer Dabbelt {
13fab957c1SPalmer Dabbelt 	asm volatile ("fence.i" ::: "memory");
14fab957c1SPalmer Dabbelt }
15fab957c1SPalmer Dabbelt 
166ca445d8SAlexandre Ghiti static inline void local_flush_icache_range(unsigned long start,
176ca445d8SAlexandre Ghiti 					    unsigned long end)
186ca445d8SAlexandre Ghiti {
196ca445d8SAlexandre Ghiti 	local_flush_icache_all();
206ca445d8SAlexandre Ghiti }
216ca445d8SAlexandre Ghiti 
2208f051edSAndrew Waterman #define PG_dcache_clean PG_arch_1
2308f051edSAndrew Waterman 
24864609c6SMatthew Wilcox (Oracle) static inline void flush_dcache_folio(struct folio *folio)
25864609c6SMatthew Wilcox (Oracle) {
26864609c6SMatthew Wilcox (Oracle) 	if (test_bit(PG_dcache_clean, &folio->flags))
27864609c6SMatthew Wilcox (Oracle) 		clear_bit(PG_dcache_clean, &folio->flags);
28864609c6SMatthew Wilcox (Oracle) }
29864609c6SMatthew Wilcox (Oracle) #define flush_dcache_folio flush_dcache_folio
30864609c6SMatthew Wilcox (Oracle) #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
31864609c6SMatthew Wilcox (Oracle) 
3208f051edSAndrew Waterman static inline void flush_dcache_page(struct page *page)
3308f051edSAndrew Waterman {
34864609c6SMatthew Wilcox (Oracle) 	flush_dcache_folio(page_folio(page));
3508f051edSAndrew Waterman }
3608f051edSAndrew Waterman 
3708f051edSAndrew Waterman /*
3808f051edSAndrew Waterman  * RISC-V doesn't have an instruction to flush parts of the instruction cache,
3908f051edSAndrew Waterman  * so instead we just flush the whole thing.
4008f051edSAndrew Waterman  */
4108f051edSAndrew Waterman #define flush_icache_range(start, end) flush_icache_all()
42885f7f8eSChristoph Hellwig #define flush_icache_user_page(vma, pg, addr, len)	\
43542124fcSYangyu Chen do {							\
44542124fcSYangyu Chen 	if (vma->vm_flags & VM_EXEC)			\
45542124fcSYangyu Chen 		flush_icache_mm(vma->vm_mm, 0);		\
46542124fcSYangyu Chen } while (0)
4708f051edSAndrew Waterman 
487e381152SAlexandre Ghiti #ifdef CONFIG_64BIT
49*503638e0SAlexandre Ghiti extern u64 new_vmalloc[NR_CPUS / sizeof(u64) + 1];
50*503638e0SAlexandre Ghiti extern char _end[];
51*503638e0SAlexandre Ghiti #define flush_cache_vmap flush_cache_vmap
52*503638e0SAlexandre Ghiti static inline void flush_cache_vmap(unsigned long start, unsigned long end)
53*503638e0SAlexandre Ghiti {
54*503638e0SAlexandre Ghiti 	if (is_vmalloc_or_module_addr((void *)start)) {
55*503638e0SAlexandre Ghiti 		int i;
56*503638e0SAlexandre Ghiti 
57*503638e0SAlexandre Ghiti 		/*
58*503638e0SAlexandre Ghiti 		 * We don't care if concurrently a cpu resets this value since
59*503638e0SAlexandre Ghiti 		 * the only place this can happen is in handle_exception() where
60*503638e0SAlexandre Ghiti 		 * an sfence.vma is emitted.
61*503638e0SAlexandre Ghiti 		 */
62*503638e0SAlexandre Ghiti 		for (i = 0; i < ARRAY_SIZE(new_vmalloc); ++i)
63*503638e0SAlexandre Ghiti 			new_vmalloc[i] = -1ULL;
64*503638e0SAlexandre Ghiti 	}
65*503638e0SAlexandre Ghiti }
667a92fc8bSAlexandre Ghiti #define flush_cache_vmap_early(start, end)	local_flush_tlb_kernel_range(start, end)
677e381152SAlexandre Ghiti #endif
687e381152SAlexandre Ghiti 
69fab957c1SPalmer Dabbelt #ifndef CONFIG_SMP
70fab957c1SPalmer Dabbelt 
7108f051edSAndrew Waterman #define flush_icache_all() local_flush_icache_all()
7208f051edSAndrew Waterman #define flush_icache_mm(mm, local) flush_icache_all()
73fab957c1SPalmer Dabbelt 
74fab957c1SPalmer Dabbelt #else /* CONFIG_SMP */
75fab957c1SPalmer Dabbelt 
7658de7754SGary Guo void flush_icache_all(void);
7708f051edSAndrew Waterman void flush_icache_mm(struct mm_struct *mm, bool local);
78fab957c1SPalmer Dabbelt 
79fab957c1SPalmer Dabbelt #endif /* CONFIG_SMP */
80fab957c1SPalmer Dabbelt 
818f7e001eSPalmer Dabbelt extern unsigned int riscv_cbom_block_size;
827ea5a736SAndrew Jones extern unsigned int riscv_cboz_block_size;
837ea5a736SAndrew Jones void riscv_init_cbo_blocksizes(void);
841631ba12SHeiko Stuebner 
851631ba12SHeiko Stuebner #ifdef CONFIG_RISCV_DMA_NONCOHERENT
861631ba12SHeiko Stuebner void riscv_noncoherent_supported(void);
8729267151SJisheng Zhang void __init riscv_set_dma_cache_alignment(void);
88f055268eSHeiko Stuebner #else
89f055268eSHeiko Stuebner static inline void riscv_noncoherent_supported(void) {}
9029267151SJisheng Zhang static inline void riscv_set_dma_cache_alignment(void) {}
911631ba12SHeiko Stuebner #endif
921631ba12SHeiko Stuebner 
93921ebd8fSAndrew Waterman /*
94921ebd8fSAndrew Waterman  * Bits in sys_riscv_flush_icache()'s flags argument.
95921ebd8fSAndrew Waterman  */
96921ebd8fSAndrew Waterman #define SYS_RISCV_FLUSH_ICACHE_LOCAL 1UL
97921ebd8fSAndrew Waterman #define SYS_RISCV_FLUSH_ICACHE_ALL   (SYS_RISCV_FLUSH_ICACHE_LOCAL)
98921ebd8fSAndrew Waterman 
99396eb69cSChristoph Hellwig #include <asm-generic/cacheflush.h>
100396eb69cSChristoph Hellwig 
101fab957c1SPalmer Dabbelt #endif /* _ASM_RISCV_CACHEFLUSH_H */
102