1 1.15 he /* $NetBSD: syncicache.c,v 1.15 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.15 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.15 he #if !defined(_STANDALONE) 40 1.1 ws #include <sys/sysctl.h> 41 1.15 he #endif 42 1.1 ws 43 1.1 ws #include <machine/cpu.h> 44 1.1 ws 45 1.6 eeh 46 1.6 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.8 dbj static struct cache_info _cache_info = { 51 1.6 eeh CACHELINESIZE, 52 1.6 eeh CACHELINESIZE, 53 1.6 eeh CACHELINESIZE, 54 1.6 eeh CACHELINESIZE 55 1.6 eeh }; 56 1.6 eeh #define CACHEINFO _cache_info 57 1.6 eeh #elif defined(_KERNEL) 58 1.6 eeh #define CACHEINFO (curcpu()->ci_ci) 59 1.1 ws #else 60 1.11 thorpej #include <stdlib.h> 61 1.11 thorpej 62 1.12 matt size_t __getcachelinesize (void); 63 1.2 tsubai 64 1.6 eeh static int _cachelinesize = 0; 65 1.6 eeh 66 1.6 eeh static struct cache_info _cache_info; 67 1.6 eeh #define CACHEINFO _cache_info 68 1.1 ws 69 1.12 matt size_t 70 1.12 matt __getcachelinesize(void) 71 1.1 ws { 72 1.1 ws static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE }; 73 1.6 eeh static int cacheinfomib[] = { CTL_MACHDEP, CPU_CACHEINFO }; 74 1.6 eeh size_t clen = sizeof(_cache_info); 75 1.6 eeh 76 1.12 matt if (_cachelinesize) 77 1.12 matt return _cachelinesize; 78 1.12 matt 79 1.6 eeh if (sysctl(cacheinfomib, sizeof(cacheinfomib) / sizeof(cacheinfomib[0]), 80 1.6 eeh &_cache_info, &clen, NULL, 0) == 0) { 81 1.6 eeh _cachelinesize = _cache_info.dcache_line_size; 82 1.12 matt return _cachelinesize; 83 1.6 eeh } 84 1.1 ws 85 1.6 eeh /* Try older deprecated sysctl */ 86 1.6 eeh clen = sizeof(_cachelinesize); 87 1.1 ws if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]), 88 1.1 ws &_cachelinesize, &clen, NULL, 0) < 0 89 1.1 ws || !_cachelinesize) 90 1.1 ws abort(); 91 1.6 eeh 92 1.6 eeh _cache_info.dcache_size = _cachelinesize; 93 1.6 eeh _cache_info.dcache_line_size = _cachelinesize; 94 1.6 eeh _cache_info.icache_size = _cachelinesize; 95 1.6 eeh _cache_info.icache_line_size = _cachelinesize; 96 1.12 matt 97 1.6 eeh /* If there is no cache, indicate we have issued the sysctl. */ 98 1.12 matt if (!_cachelinesize) 99 1.12 matt _cachelinesize = 1; 100 1.12 matt 101 1.12 matt return _cachelinesize; 102 1.1 ws } 103 1.1 ws #endif 104 1.1 ws 105 1.1 ws void 106 1.9 matt __syncicache(void *from, size_t len) 107 1.1 ws { 108 1.9 matt size_t l, off; 109 1.9 matt size_t linesz; 110 1.1 ws char *p; 111 1.1 ws 112 1.1 ws #if !defined(_KERNEL) && !defined(_STANDALONE) 113 1.1 ws if (!_cachelinesize) 114 1.12 matt __getcachelinesize(); 115 1.1 ws #endif 116 1.6 eeh 117 1.6 eeh if (CACHEINFO.dcache_size > 0) { 118 1.6 eeh linesz = CACHEINFO.dcache_line_size; 119 1.9 matt off = (uintptr_t)from & (linesz - 1); 120 1.9 matt l = (len + off + linesz - 1) & ~(linesz - 1); 121 1.6 eeh p = (char *)from - off; 122 1.6 eeh do { 123 1.14 perry __asm volatile ("dcbst 0,%0" :: "r"(p)); 124 1.6 eeh p += linesz; 125 1.9 matt } while ((l -= linesz) != 0); 126 1.6 eeh } 127 1.14 perry __asm volatile ("sync"); 128 1.6 eeh 129 1.6 eeh if (CACHEINFO.icache_size > 0 ) { 130 1.6 eeh linesz = CACHEINFO.icache_line_size; 131 1.9 matt off = (uintptr_t)from & (linesz - 1); 132 1.9 matt l = (len + off + linesz - 1) & ~(linesz - 1); 133 1.6 eeh p = (char *)from - off; 134 1.6 eeh do { 135 1.14 perry __asm volatile ("icbi 0,%0" :: "r"(p)); 136 1.6 eeh p += linesz; 137 1.9 matt } while ((l -= linesz) != 0); 138 1.6 eeh } 139 1.14 perry __asm volatile ("sync; isync"); 140 1.1 ws } 141