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