linux/arch/powerpc/include/asm/cacheflush.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   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 */
  25static 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 /* CONFIG_PPC_BOOK3S_64 */
  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 */
  38static inline void flush_dcache_page(struct page *page)
  39{
  40        if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
  41                return;
  42        /* avoid an atomic op if possible */
  43        if (test_bit(PG_dcache_clean, &page->flags))
  44                clear_bit(PG_dcache_clean, &page->flags);
  45}
  46
  47void flush_icache_range(unsigned long start, unsigned long stop);
  48#define flush_icache_range flush_icache_range
  49
  50void flush_icache_user_page(struct vm_area_struct *vma, struct page *page,
  51                unsigned long addr, int len);
  52#define flush_icache_user_page flush_icache_user_page
  53
  54void flush_dcache_icache_page(struct page *page);
  55
  56/**
  57 * flush_dcache_range(): Write any modified data cache blocks out to memory and
  58 * invalidate them. Does not invalidate the corresponding instruction cache
  59 * blocks.
  60 *
  61 * @start: the start address
  62 * @stop: the stop address (exclusive)
  63 */
  64static inline void flush_dcache_range(unsigned long start, unsigned long stop)
  65{
  66        unsigned long shift = l1_dcache_shift();
  67        unsigned long bytes = l1_dcache_bytes();
  68        void *addr = (void *)(start & ~(bytes - 1));
  69        unsigned long size = stop - (unsigned long)addr + (bytes - 1);
  70        unsigned long i;
  71
  72        if (IS_ENABLED(CONFIG_PPC64))
  73                mb();   /* sync */
  74
  75        for (i = 0; i < size >> shift; i++, addr += bytes)
  76                dcbf(addr);
  77        mb();   /* sync */
  78
  79}
  80
  81/*
  82 * Write any modified data cache blocks out to memory.
  83 * Does not invalidate the corresponding cache lines (especially for
  84 * any corresponding instruction cache).
  85 */
  86static inline void clean_dcache_range(unsigned long start, unsigned long stop)
  87{
  88        unsigned long shift = l1_dcache_shift();
  89        unsigned long bytes = l1_dcache_bytes();
  90        void *addr = (void *)(start & ~(bytes - 1));
  91        unsigned long size = stop - (unsigned long)addr + (bytes - 1);
  92        unsigned long i;
  93
  94        for (i = 0; i < size >> shift; i++, addr += bytes)
  95                dcbst(addr);
  96        mb();   /* sync */
  97}
  98
  99/*
 100 * Like above, but invalidate the D-cache.  This is used by the 8xx
 101 * to invalidate the cache so the PPC core doesn't get stale data
 102 * from the CPM (no cache snooping here :-).
 103 */
 104static inline void invalidate_dcache_range(unsigned long start,
 105                                           unsigned long stop)
 106{
 107        unsigned long shift = l1_dcache_shift();
 108        unsigned long bytes = l1_dcache_bytes();
 109        void *addr = (void *)(start & ~(bytes - 1));
 110        unsigned long size = stop - (unsigned long)addr + (bytes - 1);
 111        unsigned long i;
 112
 113        for (i = 0; i < size >> shift; i++, addr += bytes)
 114                dcbi(addr);
 115        mb();   /* sync */
 116}
 117
 118#ifdef CONFIG_4xx
 119static inline void flush_instruction_cache(void)
 120{
 121        iccci((void *)KERNELBASE);
 122        isync();
 123}
 124#else
 125void flush_instruction_cache(void);
 126#endif
 127
 128#include <asm-generic/cacheflush.h>
 129
 130#endif /* _ASM_POWERPC_CACHEFLUSH_H */
 131