cache.c revision 9202f32558601c2c99ddc438eb3218131d00d413
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for more details. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1994 - 2003 by Ralf Baechle 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cacheflush.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/processor.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cpu.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cpu-features.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Cache operations. */ 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*flush_cache_all)(void); 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*__flush_cache_all)(void); 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*flush_cache_mm)(struct mm_struct *mm); 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long end); 2553de0d471fe8ddbbeca938cffedb4cc94e04da10Ralf Baechlevoid (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, 2653de0d471fe8ddbbeca938cffedb4cc94e04da10Ralf Baechle unsigned long pfn); 27d4264f183967db9c2dae4275abb98eb1f79facb2Atsushi Nemotovoid (*flush_icache_range)(unsigned long start, unsigned long end); 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* MIPS specific cache operations */ 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*flush_cache_sigtramp)(unsigned long addr); 317e3bfc7cfc402458b0386086ab650ce811720927Ralf Baechlevoid (*local_flush_data_cache_page)(void * addr); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*flush_data_cache_page)(unsigned long addr); 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*flush_icache_all)(void); 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 359202f32558601c2c99ddc438eb3218131d00d413Ralf BaechleEXPORT_SYMBOL_GPL(local_flush_data_cache_page); 369ff77c469ed16221c6a4e882e48e4f0dcf451bdaRalf BaechleEXPORT_SYMBOL(flush_data_cache_page); 379ff77c469ed16221c6a4e882e48e4f0dcf451bdaRalf Baechle 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_DMA_NONCOHERENT 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* DMA cache operations. */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*_dma_cache_wback)(unsigned long start, unsigned long size); 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid (*_dma_cache_inv)(unsigned long start, unsigned long size); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(_dma_cache_wback_inv); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(_dma_cache_wback); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(_dma_cache_inv); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_DMA_NONCOHERENT */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We could optimize the case where the cache argument is not BCACHE but 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that seems very atypical use ... 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 55d4264f183967db9c2dae4275abb98eb1f79facb2Atsushi Nemotoasmlinkage int sys_cacheflush(unsigned long addr, 56fe00f943e0ef98b4057abcc2940d631a975b43cdRalf Baechle unsigned long bytes, unsigned int cache) 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 58750ccf687ff9adbf2a16066a3a2757d0f761384cAtsushi Nemoto if (bytes == 0) 59750ccf687ff9adbf2a16066a3a2757d0f761384cAtsushi Nemoto return 0; 60fe00f943e0ef98b4057abcc2940d631a975b43cdRalf Baechle if (!access_ok(VERIFY_WRITE, (void __user *) addr, bytes)) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flush_icache_range(addr, addr + bytes); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __flush_dcache_page(struct page *page) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct address_space *mapping = page_mapping(page); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long addr; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 73585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle if (PageHighMem(page)) 74585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle return; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mapping && !mapping_mapped(mapping)) { 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SetPageDcacheDirty(page); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We could delay the flush for the !page_mapping case too. But that 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * case is for exec env/arg pages and those are %99 certainly going to 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get faulted into the tlb (and thus flushed) anyways. 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = (unsigned long) page_address(page); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flush_data_cache_page(addr); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(__flush_dcache_page); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __update_cache(struct vm_area_struct *vma, unsigned long address, 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pte_t pte) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct page *page; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long pfn, addr; 96585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pfn = pte_pfn(pte); 99585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle if (unlikely(!pfn_valid(pfn))) 100585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle return; 101585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle page = pfn_to_page(pfn); 102585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle if (page_mapping(page) && Page_dcache_dirty(page)) { 103585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle addr = (unsigned long) page_address(page); 104585fa72493edd7d5acb308806e7bb609412c6228Ralf Baechle if (exec || pages_do_alias(addr, address & PAGE_MASK)) 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flush_data_cache_page(addr); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ClearPageDcacheDirty(page); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11002cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle#define __weak __attribute__((weak)) 11102cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle 11202cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechlestatic char cache_panic[] __initdata = "Yeee, unsupported cache architecture."; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init cpu_cache_init(void) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11602cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle if (cpu_has_3k_cache) { 11702cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle extern void __weak r3k_cache_init(void); 11802cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle 11902cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle r3k_cache_init(); 12002cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle return; 12102cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle } 12202cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle if (cpu_has_6k_cache) { 12302cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle extern void __weak r6k_cache_init(void); 12402cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle 12502cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle r6k_cache_init(); 12602cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle return; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12802cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle if (cpu_has_4k_cache) { 12902cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle extern void __weak r4k_cache_init(void); 13002cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle 13102cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle r4k_cache_init(); 13202cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle return; 13302cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle } 13402cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle if (cpu_has_8k_cache) { 13502cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle extern void __weak r8k_cache_init(void); 13602cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle 13702cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle r8k_cache_init(); 13802cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle return; 13902cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle } 14002cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle if (cpu_has_tx39_cache) { 14102cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle extern void __weak tx39_cache_init(void); 14202cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle 14302cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle tx39_cache_init(); 14402cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle return; 14502cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle } 14602cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle if (cpu_has_sb1_cache) { 14702cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle extern void __weak sb1_cache_init(void); 14802cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle 14902cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle sb1_cache_init(); 15002cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle return; 15102cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle } 15202cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle 15302cf2119684e52e97a8a90bd7630386e0f1a250aRalf Baechle panic(cache_panic); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 155