Path: blob/master/arch/tile/include/asm/cacheflush.h
10819 views
/*1* Copyright 2010 Tilera Corporation. All Rights Reserved.2*3* This program is free software; you can redistribute it and/or4* modify it under the terms of the GNU General Public License5* as published by the Free Software Foundation, version 2.6*7* This program is distributed in the hope that it will be useful, but8* WITHOUT ANY WARRANTY; without even the implied warranty of9* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or10* NON INFRINGEMENT. See the GNU General Public License for11* more details.12*/1314#ifndef _ASM_TILE_CACHEFLUSH_H15#define _ASM_TILE_CACHEFLUSH_H1617#include <arch/chip.h>1819/* Keep includes the same across arches. */20#include <linux/mm.h>21#include <linux/cache.h>22#include <asm/system.h>23#include <arch/icache.h>2425/* 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 032#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)3940/* Flush the icache just on this cpu */41extern void __flush_icache_range(unsigned long start, unsigned long end);4243/* Flush the entire icache on this cpu. */44#define __flush_icache() __flush_icache_range(0, CHIP_L1I_CACHE_SIZE())4546#ifdef CONFIG_SMP47/*48* When the kernel writes to its own text we need to do an SMP49* broadcast to make the L1I coherent everywhere. This includes50* module load and single step.51*/52extern void flush_icache_range(unsigned long start, unsigned long end);53#else54#define flush_icache_range __flush_icache_range55#endif5657/*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 context61* switch to avoid doing extra work here. But for now, I'll be62* conservative and just do a global icache flush.63*/64static inline void copy_to_user_page(struct vm_area_struct *vma,65struct page *page, unsigned long vaddr,66void *dst, void *src, int len)67{68memcpy(dst, src, len);69if (vma->vm_flags & VM_EXEC) {70flush_icache_range((unsigned long) dst,71(unsigned long) dst + len);72}73}7475#define copy_from_user_page(vma, page, vaddr, dst, src, len) \76memcpy((dst), (src), (len))7778/*79* Invalidate a VA range; pads to L2 cacheline boundaries.80*81* Note that on TILE64, __inv_buffer() actually flushes modified82* cache lines in addition to invalidating them, i.e., it's the83* same as __finv_buffer().84*/85static inline void __inv_buffer(void *buffer, size_t size)86{87char *next = (char *)((long)buffer & -L2_CACHE_BYTES);88char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size);89while (next < finish) {90__insn_inv(next);91next += CHIP_INV_STRIDE();92}93}9495/* Flush a VA range; pads to L2 cacheline boundaries. */96static inline void __flush_buffer(void *buffer, size_t size)97{98char *next = (char *)((long)buffer & -L2_CACHE_BYTES);99char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size);100while (next < finish) {101__insn_flush(next);102next += CHIP_FLUSH_STRIDE();103}104}105106/* Flush & invalidate a VA range; pads to L2 cacheline boundaries. */107static inline void __finv_buffer(void *buffer, size_t size)108{109char *next = (char *)((long)buffer & -L2_CACHE_BYTES);110char *finish = (char *)L2_CACHE_ALIGN((long)buffer + size);111while (next < finish) {112__insn_finv(next);113next += CHIP_FINV_STRIDE();114}115}116117118/* Invalidate a VA range and wait for it to be complete. */119static inline void inv_buffer(void *buffer, size_t size)120{121__inv_buffer(buffer, size);122mb();123}124125/*126* Flush a locally-homecached VA range and wait for the evicted127* cachelines to hit memory.128*/129static inline void flush_buffer_local(void *buffer, size_t size)130{131__flush_buffer(buffer, size);132mb_incoherent();133}134135/*136* Flush and invalidate a locally-homecached VA range and wait for the137* evicted cachelines to hit memory.138*/139static inline void finv_buffer_local(void *buffer, size_t size)140{141__finv_buffer(buffer, size);142mb_incoherent();143}144145/*146* Flush and invalidate a VA range that is homed remotely, waiting147* until the memory controller holds the flushed values. If "hfh" is148* true, we will do a more expensive flush involving additional loads149* to make sure we have touched all the possible home cpus of a buffer150* that is homed with "hash for home".151*/152void finv_buffer_remote(void *buffer, size_t size, int hfh);153154#endif /* _ASM_TILE_CACHEFLUSH_H */155156157