1 1.14 he /* $NetBSD: syncicache.c,v 1.14 2008/03/18 20:11:43 he Exp $ */ 2 1.1 ws 3 1.1 ws /* 4 1.1 ws * Copyright (C) 1995-1997, 1999 Wolfgang Solfrank. 5 1.1 ws * Copyright (C) 1995-1997, 1999 TooLs GmbH. 6 1.1 ws * All rights reserved. 7 1.1 ws * 8 1.1 ws * Redistribution and use in source and binary forms, with or without 9 1.1 ws * modification, are permitted provided that the following conditions 10 1.1 ws * are met: 11 1.1 ws * 1. Redistributions of source code must retain the above copyright 12 1.1 ws * notice, this list of conditions and the following disclaimer. 13 1.1 ws * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 ws * notice, this list of conditions and the following disclaimer in the 15 1.1 ws * documentation and/or other materials provided with the distribution. 16 1.1 ws * 3. All advertising materials mentioning features or use of this software 17 1.1 ws * must display the following acknowledgement: 18 1.1 ws * This product includes software developed by TooLs GmbH. 19 1.1 ws * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 1.1 ws * derived from this software without specific prior written permission. 21 1.1 ws * 22 1.1 ws * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 1.1 ws * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 ws * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 ws * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 1.1 ws * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 1.1 ws * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 1.1 ws * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 1.1 ws * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 1.1 ws * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 1.1 ws * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 ws */ 33 1.1 ws #include <sys/param.h> 34 1.14 he #if defined(_KERNEL) 35 1.2 tsubai #include <sys/time.h> 36 1.1 ws #include <sys/proc.h> 37 1.3 mrg #include <uvm/uvm_extern.h> 38 1.1 ws #endif 39 1.14 he #if !defined(_STANDALONE) 40 1.1 ws #include <sys/sysctl.h> 41 1.14 he #endif 42 1.1 ws 43 1.1 ws #include <machine/cpu.h> 44 1.1 ws 45 1.5 eeh 46 1.5 eeh #if defined(_STANDALONE) 47 1.1 ws #ifndef CACHELINESIZE 48 1.1 ws #error "Must know the size of a cache line" 49 1.1 ws #endif 50 1.6 dbj static struct cache_info _cache_info = { 51 1.5 eeh CACHELINESIZE, 52 1.5 eeh CACHELINESIZE, 53 1.5 eeh CACHELINESIZE, 54 1.5 eeh CACHELINESIZE 55 1.5 eeh }; 56 1.5 eeh #define CACHEINFO _cache_info 57 1.5 eeh #elif defined(_KERNEL) 58 1.5 eeh #define CACHEINFO (curcpu()->ci_ci) 59 1.1 ws #else 60 1.5 eeh static void getcachelinesize (void); 61 1.2 tsubai 62 1.5 eeh static int _cachelinesize = 0; 63 1.5 eeh 64 1.5 eeh static struct cache_info _cache_info; 65 1.5 eeh #define CACHEINFO _cache_info 66 1.1 ws 67 1.1 ws static void 68 1.5 eeh getcachelinesize(void) 69 1.1 ws { 70 1.1 ws static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE }; 71 1.5 eeh static int cacheinfomib[] = { CTL_MACHDEP, CPU_CACHEINFO }; 72 1.5 eeh size_t clen = sizeof(_cache_info); 73 1.5 eeh 74 1.5 eeh if (sysctl(cacheinfomib, sizeof(cacheinfomib) / sizeof(cacheinfomib[0]), 75 1.5 eeh &_cache_info, &clen, NULL, 0) == 0) { 76 1.5 eeh _cachelinesize = _cache_info.dcache_line_size; 77 1.5 eeh return; 78 1.5 eeh } 79 1.1 ws 80 1.5 eeh /* Try older deprecated sysctl */ 81 1.5 eeh clen = sizeof(_cachelinesize); 82 1.1 ws if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]), 83 1.1 ws &_cachelinesize, &clen, NULL, 0) < 0 84 1.1 ws || !_cachelinesize) 85 1.1 ws abort(); 86 1.5 eeh 87 1.5 eeh _cache_info.dcache_size = _cachelinesize; 88 1.5 eeh _cache_info.dcache_line_size = _cachelinesize; 89 1.5 eeh _cache_info.icache_size = _cachelinesize; 90 1.5 eeh _cache_info.icache_line_size = _cachelinesize; 91 1.5 eeh /* If there is no cache, indicate we have issued the sysctl. */ 92 1.10 simonb if (!_cachelinesize) 93 1.10 simonb _cachelinesize = 1; 94 1.1 ws } 95 1.1 ws #endif 96 1.1 ws 97 1.1 ws void 98 1.7 matt __syncicache(void *from, size_t len) 99 1.1 ws { 100 1.7 matt size_t l, off; 101 1.7 matt size_t linesz; 102 1.1 ws char *p; 103 1.1 ws 104 1.1 ws #if !defined(_KERNEL) && !defined(_STANDALONE) 105 1.1 ws if (!_cachelinesize) 106 1.1 ws getcachelinesize(); 107 1.9 perry #endif 108 1.5 eeh 109 1.5 eeh if (CACHEINFO.dcache_size > 0) { 110 1.5 eeh linesz = CACHEINFO.dcache_line_size; 111 1.7 matt off = (uintptr_t)from & (linesz - 1); 112 1.7 matt l = (len + off + linesz - 1) & ~(linesz - 1); 113 1.5 eeh p = (char *)from - off; 114 1.5 eeh do { 115 1.13 perry __asm volatile ("dcbst 0,%0" :: "r"(p)); 116 1.5 eeh p += linesz; 117 1.7 matt } while ((l -= linesz) != 0); 118 1.5 eeh } 119 1.13 perry __asm volatile ("sync"); 120 1.5 eeh 121 1.5 eeh if (CACHEINFO.icache_size > 0 ) { 122 1.5 eeh linesz = CACHEINFO.icache_line_size; 123 1.7 matt off = (uintptr_t)from & (linesz - 1); 124 1.7 matt l = (len + off + linesz - 1) & ~(linesz - 1); 125 1.5 eeh p = (char *)from - off; 126 1.5 eeh do { 127 1.13 perry __asm volatile ("icbi 0,%0" :: "r"(p)); 128 1.5 eeh p += linesz; 129 1.7 matt } while ((l -= linesz) != 0); 130 1.5 eeh } 131 1.13 perry __asm volatile ("sync; isync"); 132 1.1 ws } 133