···11+/*22+ * Copyright (C) 2004 Microtronix Datacom Ltd.33+ *44+ * All rights reserved.55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ *1111+ * This program is distributed in the hope that it will be useful, but1212+ * WITHOUT ANY WARRANTY; without even the implied warranty of1313+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or1414+ * NON INFRINGEMENT. See the GNU General Public License for more1515+ * details.1616+ */1717+1818+#ifndef _ASM_NIOS2_CACHE_H1919+#define _ASM_NIOS2_CACHE_H2020+2121+#define NIOS2_DCACHE_SIZE CONFIG_NIOS2_DCACHE_SIZE2222+#define NIOS2_ICACHE_SIZE CONFIG_NIOS2_ICACHE_SIZE2323+#define NIOS2_DCACHE_LINE_SIZE CONFIG_NIOS2_DCACHE_LINE_SIZE2424+#define NIOS2_ICACHE_LINE_SHIFT 52525+#define NIOS2_ICACHE_LINE_SIZE (1 << NIOS2_ICACHE_LINE_SHIFT)2626+2727+/* bytes per L1 cache line */2828+#define L1_CACHE_SHIFT NIOS2_ICACHE_LINE_SHIFT2929+#define L1_CACHE_BYTES NIOS2_ICACHE_LINE_SIZE3030+3131+#define ARCH_DMA_MINALIGN L1_CACHE_BYTES3232+3333+#define __cacheline_aligned3434+#define ____cacheline_aligned3535+3636+#endif
+52
arch/nios2/include/asm/cacheflush.h
···11+/*22+ * Copyright (C) 2003 Microtronix Datacom Ltd.33+ * Copyright (C) 2000-2002 Greg Ungerer <gerg@snapgear.com>44+ *55+ * This file is subject to the terms and conditions of the GNU General Public66+ * License. See the file "COPYING" in the main directory of this archive77+ * for more details.88+ */99+1010+#ifndef _ASM_NIOS2_CACHEFLUSH_H1111+#define _ASM_NIOS2_CACHEFLUSH_H1212+1313+#include <linux/mm_types.h>1414+1515+/*1616+ * This flag is used to indicate that the page pointed to by a pte is clean1717+ * and does not require cleaning before returning it to the user.1818+ */1919+#define PG_dcache_clean PG_arch_12020+2121+struct mm_struct;2222+2323+extern void flush_cache_all(void);2424+extern void flush_cache_mm(struct mm_struct *mm);2525+extern void flush_cache_dup_mm(struct mm_struct *mm);2626+extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,2727+ unsigned long end);2828+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,2929+ unsigned long pfn);3030+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 13131+extern void flush_dcache_page(struct page *page);3232+3333+extern void flush_icache_range(unsigned long start, unsigned long end);3434+extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);3535+3636+#define flush_cache_vmap(start, end) flush_dcache_range(start, end)3737+#define flush_cache_vunmap(start, end) flush_dcache_range(start, end)3838+3939+extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page,4040+ unsigned long user_vaddr,4141+ void *dst, void *src, int len);4242+extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page,4343+ unsigned long user_vaddr,4444+ void *dst, void *src, int len);4545+4646+extern void flush_dcache_range(unsigned long start, unsigned long end);4747+extern void invalidate_dcache_range(unsigned long start, unsigned long end);4848+4949+#define flush_dcache_mmap_lock(mapping) do { } while (0)5050+#define flush_dcache_mmap_unlock(mapping) do { } while (0)5151+5252+#endif /* _ASM_NIOS2_CACHEFLUSH_H */
+271
arch/nios2/mm/cacheflush.c
···11+/*22+ * This file is subject to the terms and conditions of the GNU General Public33+ * License. See the file "COPYING" in the main directory of this archive44+ * for more details.55+ *66+ * Copyright (C) 2009, Wind River Systems Inc77+ * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com88+ */99+1010+#include <linux/export.h>1111+#include <linux/sched.h>1212+#include <linux/mm.h>1313+#include <linux/fs.h>1414+1515+#include <asm/cacheflush.h>1616+#include <asm/cpuinfo.h>1717+1818+static void __flush_dcache(unsigned long start, unsigned long end)1919+{2020+ unsigned long addr;2121+2222+ start &= ~(cpuinfo.dcache_line_size - 1);2323+ end += (cpuinfo.dcache_line_size - 1);2424+ end &= ~(cpuinfo.dcache_line_size - 1);2525+2626+ if (end > start + cpuinfo.dcache_size)2727+ end = start + cpuinfo.dcache_size;2828+2929+ for (addr = start; addr < end; addr += cpuinfo.dcache_line_size) {3030+ __asm__ __volatile__ (" flushda 0(%0)\n"3131+ : /* Outputs */3232+ : /* Inputs */ "r"(addr)3333+ /* : No clobber */);3434+ }3535+}3636+3737+static void __flush_dcache_all(unsigned long start, unsigned long end)3838+{3939+ unsigned long addr;4040+4141+ start &= ~(cpuinfo.dcache_line_size - 1);4242+ end += (cpuinfo.dcache_line_size - 1);4343+ end &= ~(cpuinfo.dcache_line_size - 1);4444+4545+ if (end > start + cpuinfo.dcache_size)4646+ end = start + cpuinfo.dcache_size;4747+4848+ for (addr = start; addr < end; addr += cpuinfo.dcache_line_size) {4949+ __asm__ __volatile__ (" flushd 0(%0)\n"5050+ : /* Outputs */5151+ : /* Inputs */ "r"(addr)5252+ /* : No clobber */);5353+ }5454+}5555+5656+static void __invalidate_dcache(unsigned long start, unsigned long end)5757+{5858+ unsigned long addr;5959+6060+ start &= ~(cpuinfo.dcache_line_size - 1);6161+ end += (cpuinfo.dcache_line_size - 1);6262+ end &= ~(cpuinfo.dcache_line_size - 1);6363+6464+ if (end > start + cpuinfo.dcache_size)6565+ end = start + cpuinfo.dcache_size;6666+6767+ for (addr = start; addr < end; addr += cpuinfo.dcache_line_size) {6868+ __asm__ __volatile__ (" initda 0(%0)\n"6969+ : /* Outputs */7070+ : /* Inputs */ "r"(addr)7171+ /* : No clobber */);7272+ }7373+}7474+7575+static void __flush_icache(unsigned long start, unsigned long end)7676+{7777+ unsigned long addr;7878+7979+ start &= ~(cpuinfo.icache_line_size - 1);8080+ end += (cpuinfo.icache_line_size - 1);8181+ end &= ~(cpuinfo.icache_line_size - 1);8282+8383+ if (end > start + cpuinfo.icache_size)8484+ end = start + cpuinfo.icache_size;8585+8686+ for (addr = start; addr < end; addr += cpuinfo.icache_line_size) {8787+ __asm__ __volatile__ (" flushi %0\n"8888+ : /* Outputs */8989+ : /* Inputs */ "r"(addr)9090+ /* : No clobber */);9191+ }9292+ __asm__ __volatile(" flushp\n");9393+}9494+9595+static void flush_aliases(struct address_space *mapping, struct page *page)9696+{9797+ struct mm_struct *mm = current->active_mm;9898+ struct vm_area_struct *mpnt;9999+ pgoff_t pgoff;100100+101101+ pgoff = page->index;102102+103103+ flush_dcache_mmap_lock(mapping);104104+ vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {105105+ unsigned long offset;106106+107107+ if (mpnt->vm_mm != mm)108108+ continue;109109+ if (!(mpnt->vm_flags & VM_MAYSHARE))110110+ continue;111111+112112+ offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;113113+ flush_cache_page(mpnt, mpnt->vm_start + offset,114114+ page_to_pfn(page));115115+ }116116+ flush_dcache_mmap_unlock(mapping);117117+}118118+119119+void flush_cache_all(void)120120+{121121+ __flush_dcache_all(0, cpuinfo.dcache_size);122122+ __flush_icache(0, cpuinfo.icache_size);123123+}124124+125125+void flush_cache_mm(struct mm_struct *mm)126126+{127127+ flush_cache_all();128128+}129129+130130+void flush_cache_dup_mm(struct mm_struct *mm)131131+{132132+ flush_cache_all();133133+}134134+135135+void flush_icache_range(unsigned long start, unsigned long end)136136+{137137+ __flush_icache(start, end);138138+}139139+140140+void flush_dcache_range(unsigned long start, unsigned long end)141141+{142142+ __flush_dcache(start, end);143143+}144144+EXPORT_SYMBOL(flush_dcache_range);145145+146146+void invalidate_dcache_range(unsigned long start, unsigned long end)147147+{148148+ __invalidate_dcache(start, end);149149+}150150+EXPORT_SYMBOL(invalidate_dcache_range);151151+152152+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,153153+ unsigned long end)154154+{155155+ __flush_dcache(start, end);156156+ if (vma == NULL || (vma->vm_flags & VM_EXEC))157157+ __flush_icache(start, end);158158+}159159+160160+void flush_icache_page(struct vm_area_struct *vma, struct page *page)161161+{162162+ unsigned long start = (unsigned long) page_address(page);163163+ unsigned long end = start + PAGE_SIZE;164164+165165+ __flush_icache(start, end);166166+}167167+168168+void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,169169+ unsigned long pfn)170170+{171171+ unsigned long start = vmaddr;172172+ unsigned long end = start + PAGE_SIZE;173173+174174+ __flush_dcache(start, end);175175+ if (vma->vm_flags & VM_EXEC)176176+ __flush_icache(start, end);177177+}178178+179179+void flush_dcache_page(struct page *page)180180+{181181+ struct address_space *mapping;182182+183183+ /*184184+ * The zero page is never written to, so never has any dirty185185+ * cache lines, and therefore never needs to be flushed.186186+ */187187+ if (page == ZERO_PAGE(0))188188+ return;189189+190190+ mapping = page_mapping(page);191191+192192+ /* Flush this page if there are aliases. */193193+ if (mapping && !mapping_mapped(mapping)) {194194+ clear_bit(PG_dcache_clean, &page->flags);195195+ } else {196196+ unsigned long start = (unsigned long)page_address(page);197197+198198+ __flush_dcache_all(start, start + PAGE_SIZE);199199+ if (mapping)200200+ flush_aliases(mapping, page);201201+ set_bit(PG_dcache_clean, &page->flags);202202+ }203203+}204204+EXPORT_SYMBOL(flush_dcache_page);205205+206206+void update_mmu_cache(struct vm_area_struct *vma,207207+ unsigned long address, pte_t *pte)208208+{209209+ unsigned long pfn = pte_pfn(*pte);210210+ struct page *page;211211+212212+ if (!pfn_valid(pfn))213213+ return;214214+215215+ /*216216+ * The zero page is never written to, so never has any dirty217217+ * cache lines, and therefore never needs to be flushed.218218+ */219219+ page = pfn_to_page(pfn);220220+ if (page == ZERO_PAGE(0))221221+ return;222222+223223+ if (!PageReserved(page) &&224224+ !test_and_set_bit(PG_dcache_clean, &page->flags)) {225225+ unsigned long start = page_to_virt(page);226226+ struct address_space *mapping;227227+228228+ __flush_dcache(start, start + PAGE_SIZE);229229+230230+ mapping = page_mapping(page);231231+ if (mapping)232232+ flush_aliases(mapping, page);233233+ }234234+}235235+236236+void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,237237+ struct page *to)238238+{239239+ __flush_dcache(vaddr, vaddr + PAGE_SIZE);240240+ copy_page(vto, vfrom);241241+ __flush_dcache((unsigned long)vto, (unsigned long)vto + PAGE_SIZE);242242+}243243+244244+void clear_user_page(void *addr, unsigned long vaddr, struct page *page)245245+{246246+ __flush_dcache(vaddr, vaddr + PAGE_SIZE);247247+ clear_page(addr);248248+ __flush_dcache((unsigned long)addr, (unsigned long)addr + PAGE_SIZE);249249+}250250+251251+void copy_from_user_page(struct vm_area_struct *vma, struct page *page,252252+ unsigned long user_vaddr,253253+ void *dst, void *src, int len)254254+{255255+ flush_cache_page(vma, user_vaddr, page_to_pfn(page));256256+ memcpy(dst, src, len);257257+ __flush_dcache((unsigned long)src, (unsigned long)src + len);258258+ if (vma->vm_flags & VM_EXEC)259259+ __flush_icache((unsigned long)src, (unsigned long)src + len);260260+}261261+262262+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,263263+ unsigned long user_vaddr,264264+ void *dst, void *src, int len)265265+{266266+ flush_cache_page(vma, user_vaddr, page_to_pfn(page));267267+ memcpy(dst, src, len);268268+ __flush_dcache((unsigned long)dst, (unsigned long)dst + len);269269+ if (vma->vm_flags & VM_EXEC)270270+ __flush_icache((unsigned long)dst, (unsigned long)dst + len);271271+}