| 1 |
|
| 2 | |
| 3 |
|
| 4 | #ifndef _ASM_POWERPC_CACHEFLUSH_H
|
| 5 | #define _ASM_POWERPC_CACHEFLUSH_H
|
| 6 |
|
| 7 | #include <linux/mm.h>
|
| 8 | #include <asm/cputable.h>
|
| 9 | #include <asm/cpu_has_feature.h>
|
| 10 |
|
| 11 | |
| 12 | * This flag is used to indicate that the page pointed to by a pte is clean
|
| 13 | * and does not require cleaning before returning it to the user.
|
| 14 |
|
| 15 | #define PG_dcache_clean PG_arch_1
|
| 16 |
|
| 17 | #ifdef CONFIG_PPC_BOOK3S_64
|
| 18 | |
| 19 | * Book3s has no ptesync after setting a pte, so without this ptesync it's
|
| 20 | * possible for a kernel virtual mapping access to return a spurious fault
|
| 21 | * if it's accessed right after the pte is set. The page fault handler does
|
| 22 | * not expect this type of fault. flush_cache_vmap is not exactly the right
|
| 23 | * place to put this, but it seems to work well enough.
|
| 24 |
|
| 25 | static inline void flush_cache_vmap(unsigned long start, unsigned long end)
|
| 26 | {
|
| 27 | asm volatile("ptesync" ::: "memory");
|
| 28 | }
|
| 29 | #define flush_cache_vmap flush_cache_vmap
|
| 30 | #endif
|
| 31 |
|
| 32 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
| 33 | |
| 34 | * This is called when a page has been modified by the kernel.
|
| 35 | * It just marks the page as not i-cache clean. We do the i-cache
|
| 36 | * flush later when the page is given to a user process, if necessary.
|
| 37 |
|
| 38 | static inline void flush_dcache_folio(struct folio *folio)
|
| 39 | {
|
| 40 | if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
|
| 41 | return;
|
| 42 |
|
| 43 | if (test_bit(PG_dcache_clean, &folio->flags.f))
|
| 44 | clear_bit(PG_dcache_clean, &folio->flags.f);
|
| 45 | }
|
| 46 | #define flush_dcache_folio flush_dcache_folio
|
| 47 |
|
| 48 | static inline void flush_dcache_page(struct page *page)
|
| 49 | {
|
| 50 | flush_dcache_folio(page_folio(page));
|
| 51 | }
|
| 52 |
|
| 53 | void flush_icache_range(unsigned long start, unsigned long stop);
|
| 54 | #define flush_icache_range flush_icache_range
|
| 55 |
|
| 56 | void flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
|
| 57 | unsigned long addr, int len);
|
| 58 | #define flush_icache_user_page flush_icache_user_page
|
| 59 |
|
| 60 | void flush_dcache_icache_folio(struct folio *folio);
|
| 61 |
|
| 62 | |
| 63 | * flush_dcache_range(): Write any modified data cache blocks out to memory and
|
| 64 | * invalidate them. Does not invalidate the corresponding instruction cache
|
| 65 | * blocks.
|
| 66 | *
|
| 67 | * @start: the start address
|
| 68 | * @stop: the stop address (exclusive)
|
| 69 |
|
| 70 | static inline void flush_dcache_range(unsigned long start, unsigned long stop)
|
| 71 | {
|
| 72 | unsigned long shift = l1_dcache_shift();
|
| 73 | unsigned long bytes = l1_dcache_bytes();
|
| 74 | void *addr = (void *)(start & ~(bytes - 1));
|
| 75 | unsigned long size = stop - (unsigned long)addr + (bytes - 1);
|
| 76 | unsigned long i;
|
| 77 |
|
| 78 | if (IS_ENABLED(CONFIG_PPC64))
|
| 79 | mb();
|
| 80 |
|
| 81 | for (i = 0; i < size >> shift; i++, addr += bytes)
|
| 82 | dcbf(addr);
|
| 83 | mb();
|
| 84 |
|
| 85 | }
|
| 86 |
|
| 87 | |
| 88 | * Write any modified data cache blocks out to memory.
|
| 89 | * Does not invalidate the corresponding cache lines (especially for
|
| 90 | * any corresponding instruction cache).
|
| 91 |
|
| 92 | static inline void clean_dcache_range(unsigned long start, unsigned long stop)
|
| 93 | {
|
| 94 | unsigned long shift = l1_dcache_shift();
|
| 95 | unsigned long bytes = l1_dcache_bytes();
|
| 96 | void *addr = (void *)(start & ~(bytes - 1));
|
| 97 | unsigned long size = stop - (unsigned long)addr + (bytes - 1);
|
| 98 | unsigned long i;
|
| 99 |
|
| 100 | for (i = 0; i < size >> shift; i++, addr += bytes)
|
| 101 | dcbst(addr);
|
| 102 | mb();
|
| 103 | }
|
| 104 |
|
| 105 | |
| 106 | * Like above, but invalidate the D-cache. This is used by the 8xx
|
| 107 | * to invalidate the cache so the PPC core doesn't get stale data
|
| 108 | * from the CPM (no cache snooping here :-).
|
| 109 |
|
| 110 | static inline void invalidate_dcache_range(unsigned long start,
|
| 111 | unsigned long stop)
|
| 112 | {
|
| 113 | unsigned long shift = l1_dcache_shift();
|
| 114 | unsigned long bytes = l1_dcache_bytes();
|
| 115 | void *addr = (void *)(start & ~(bytes - 1));
|
| 116 | unsigned long size = stop - (unsigned long)addr + (bytes - 1);
|
| 117 | unsigned long i;
|
| 118 |
|
| 119 | for (i = 0; i < size >> shift; i++, addr += bytes)
|
| 120 | dcbi(addr);
|
| 121 | mb();
|
| 122 | }
|
| 123 |
|
| 124 | #ifdef CONFIG_44x
|
| 125 | static inline void flush_instruction_cache(void)
|
| 126 | {
|
| 127 | iccci((void *)KERNELBASE);
|
| 128 | isync();
|
| 129 | }
|
| 130 | #else
|
| 131 | void flush_instruction_cache(void);
|
| 132 | #endif
|
| 133 |
|
| 134 | #include <asm-generic/cacheflush.h>
|
| 135 |
|
| 136 | #endif
|