1/* 2 * Copyright 2010 Tilera Corporation. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, version 2. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 11 * NON INFRINGEMENT. See the GNU General Public License for 12 * more details. 13 */ 14 15#ifndef _ASM_TILE_CACHEFLUSH_H 16#define _ASM_TILE_CACHEFLUSH_H 17 18#include <arch/chip.h> 19 20/* Keep includes the same across arches. */ 21#include <linux/mm.h> 22#include <linux/cache.h> 23#include <arch/icache.h> 24 25/* Caches are physically-indexed and so don't need special treatment */ 26#define flush_cache_all() do { } while (0) 27#define flush_cache_mm(mm) do { } while (0) 28#define flush_cache_dup_mm(mm) do { } while (0) 29#define flush_cache_range(vma, start, end) do { } while (0) 30#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) 31#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 32#define flush_dcache_page(page) do { } while (0) 33#define flush_dcache_mmap_lock(mapping) do { } while (0) 34#define flush_dcache_mmap_unlock(mapping) do { } while (0) 35#define flush_cache_vmap(start, end) do { } while (0) 36#define flush_cache_vunmap(start, end) do { } while (0) 37#define flush_icache_page(vma, pg) do { } while (0) 38#define flush_icache_user_range(vma, pg, adr, len) do { } while (0) 39 40/* Flush the icache just on this cpu */ 41extern void __flush_icache_range(unsigned long start, unsigned long end); 42 43/* Flush the entire icache on this cpu. */ 44#define __flush_icache() __flush_icache_range(0, CHIP_L1I_CACHE_SIZE()) 45 46#ifdef CONFIG_SMP 47/* 48 * When the kernel writes to its own text we need to do an SMP 49 * broadcast to make the L1I coherent everywhere. This includes 50 * module load and single step. 51 */ 52extern void flush_icache_range(unsigned long start, unsigned long end); 53#else 54#define flush_icache_range __flush_icache_range 55#endif 56 57/* 58 * An update to an executable user page requires icache flushing. 59 * We could carefully update only tiles that are running this process, 60 * and rely on the fact that we flush the icache on every context 61 * switch to avoid doing extra work here. But for now, I'll be 62 * conservative and just do a global icache flush. 63 */ 64static inline void copy_to_user_page(struct vm_area_struct *vma, 65 struct page *page, unsigned long vaddr, 66 void *dst, void *src, int len) 67{ 68 memcpy(dst, src, len); 69 if (vma->vm_flags & VM_EXEC) { 70 flush_icache_range((unsigned long) dst, 71 (unsigned long) dst + len); 72 } 73} 74 75#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ 76 memcpy((dst), (src), (len)) 77 78/* Flush a VA range; pads to L2 cacheline boundaries. */ 79static inline void __flush_buffer(void *buffer, size_t size) 80{ 81 char *next = (char *)((long)buffer & -L2_CACHE_BYTES); 82 char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size); 83 while (next < finish) { 84 __insn_flush(next); 85 next += CHIP_FLUSH_STRIDE(); 86 } 87} 88 89/* Flush & invalidate a VA range; pads to L2 cacheline boundaries. */ 90static inline void __finv_buffer(void *buffer, size_t size) 91{ 92 char *next = (char *)((long)buffer & -L2_CACHE_BYTES); 93 char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size); 94 while (next < finish) { 95 __insn_finv(next); 96 next += CHIP_FINV_STRIDE(); 97 } 98} 99 100 101/* 102 * Flush a locally-homecached VA range and wait for the evicted 103 * cachelines to hit memory. 104 */ 105static inline void flush_buffer_local(void *buffer, size_t size) 106{ 107 __flush_buffer(buffer, size); 108 mb_incoherent(); 109} 110 111/* 112 * Flush and invalidate a locally-homecached VA range and wait for the 113 * evicted cachelines to hit memory. 114 */ 115static inline void finv_buffer_local(void *buffer, size_t size) 116{ 117 __finv_buffer(buffer, size); 118 mb_incoherent(); 119} 120 121#ifdef __tilepro__ 122/* Invalidate a VA range; pads to L2 cacheline boundaries. */ 123static inline void __inv_buffer(void *buffer, size_t size) 124{ 125 char *next = (char *)((long)buffer & -L2_CACHE_BYTES); 126 char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size); 127 while (next < finish) { 128 __insn_inv(next); 129 next += CHIP_INV_STRIDE(); 130 } 131} 132 133/* Invalidate a VA range and wait for it to be complete. */ 134static inline void inv_buffer(void *buffer, size_t size) 135{ 136 __inv_buffer(buffer, size); 137 mb(); 138} 139#endif 140 141/* 142 * Flush and invalidate a VA range that is homed remotely, waiting 143 * until the memory controller holds the flushed values. If "hfh" is 144 * true, we will do a more expensive flush involving additional loads 145 * to make sure we have touched all the possible home cpus of a buffer 146 * that is homed with "hash for home". 147 */ 148void finv_buffer_remote(void *buffer, size_t size, int hfh); 149 150/* 151 * On SMP systems, when the scheduler does migration-cost autodetection, 152 * it needs a way to flush as much of the CPU's caches as possible: 153 * 154 * TODO: fill this in! 155 */ 156static inline void sched_cacheflush(void) 157{ 158} 159 160#endif /* _ASM_TILE_CACHEFLUSH_H */ 161