1*0db6a6b0She /* $NetBSD: syncicache.c,v 1.14 2008/03/18 20:11:43 he Exp $ */
254230938Sws
354230938Sws /*
454230938Sws * Copyright (C) 1995-1997, 1999 Wolfgang Solfrank.
554230938Sws * Copyright (C) 1995-1997, 1999 TooLs GmbH.
654230938Sws * All rights reserved.
754230938Sws *
854230938Sws * Redistribution and use in source and binary forms, with or without
954230938Sws * modification, are permitted provided that the following conditions
1054230938Sws * are met:
1154230938Sws * 1. Redistributions of source code must retain the above copyright
1254230938Sws * notice, this list of conditions and the following disclaimer.
1354230938Sws * 2. Redistributions in binary form must reproduce the above copyright
1454230938Sws * notice, this list of conditions and the following disclaimer in the
1554230938Sws * documentation and/or other materials provided with the distribution.
1654230938Sws * 3. All advertising materials mentioning features or use of this software
1754230938Sws * must display the following acknowledgement:
1854230938Sws * This product includes software developed by TooLs GmbH.
1954230938Sws * 4. The name of TooLs GmbH may not be used to endorse or promote products
2054230938Sws * derived from this software without specific prior written permission.
2154230938Sws *
2254230938Sws * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2354230938Sws * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2454230938Sws * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2554230938Sws * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2654230938Sws * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2754230938Sws * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2854230938Sws * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2954230938Sws * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3054230938Sws * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3154230938Sws * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3254230938Sws */
3354230938Sws #include <sys/param.h>
34*0db6a6b0She #if defined(_KERNEL)
35a5bf1bf4Stsubai #include <sys/time.h>
3654230938Sws #include <sys/proc.h>
37de53718bSmrg #include <uvm/uvm_extern.h>
3854230938Sws #endif
39*0db6a6b0She #if !defined(_STANDALONE)
4054230938Sws #include <sys/sysctl.h>
41*0db6a6b0She #endif
4254230938Sws
4354230938Sws #include <machine/cpu.h>
4454230938Sws
454c434f62Seeh
464c434f62Seeh #if defined(_STANDALONE)
4754230938Sws #ifndef CACHELINESIZE
4854230938Sws #error "Must know the size of a cache line"
4954230938Sws #endif
50f0658bdaSdbj static struct cache_info _cache_info = {
514c434f62Seeh CACHELINESIZE,
524c434f62Seeh CACHELINESIZE,
534c434f62Seeh CACHELINESIZE,
544c434f62Seeh CACHELINESIZE
554c434f62Seeh };
564c434f62Seeh #define CACHEINFO _cache_info
574c434f62Seeh #elif defined(_KERNEL)
584c434f62Seeh #define CACHEINFO (curcpu()->ci_ci)
5954230938Sws #else
604c434f62Seeh static void getcachelinesize (void);
61a5bf1bf4Stsubai
624c434f62Seeh static int _cachelinesize = 0;
634c434f62Seeh
644c434f62Seeh static struct cache_info _cache_info;
654c434f62Seeh #define CACHEINFO _cache_info
6654230938Sws
6754230938Sws static void
getcachelinesize(void)684c434f62Seeh getcachelinesize(void)
6954230938Sws {
7054230938Sws static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE };
714c434f62Seeh static int cacheinfomib[] = { CTL_MACHDEP, CPU_CACHEINFO };
724c434f62Seeh size_t clen = sizeof(_cache_info);
7354230938Sws
744c434f62Seeh if (sysctl(cacheinfomib, sizeof(cacheinfomib) / sizeof(cacheinfomib[0]),
754c434f62Seeh &_cache_info, &clen, NULL, 0) == 0) {
764c434f62Seeh _cachelinesize = _cache_info.dcache_line_size;
774c434f62Seeh return;
784c434f62Seeh }
794c434f62Seeh
804c434f62Seeh /* Try older deprecated sysctl */
814c434f62Seeh clen = sizeof(_cachelinesize);
8254230938Sws if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]),
8354230938Sws &_cachelinesize, &clen, NULL, 0) < 0
8454230938Sws || !_cachelinesize)
8554230938Sws abort();
864c434f62Seeh
874c434f62Seeh _cache_info.dcache_size = _cachelinesize;
884c434f62Seeh _cache_info.dcache_line_size = _cachelinesize;
894c434f62Seeh _cache_info.icache_size = _cachelinesize;
904c434f62Seeh _cache_info.icache_line_size = _cachelinesize;
914c434f62Seeh /* If there is no cache, indicate we have issued the sysctl. */
92bdc552eaSsimonb if (!_cachelinesize)
93bdc552eaSsimonb _cachelinesize = 1;
9454230938Sws }
9554230938Sws #endif
9654230938Sws
9754230938Sws void
__syncicache(void * from,size_t len)9812810ed3Smatt __syncicache(void *from, size_t len)
9954230938Sws {
10012810ed3Smatt size_t l, off;
10112810ed3Smatt size_t linesz;
10254230938Sws char *p;
10354230938Sws
10454230938Sws #if !defined(_KERNEL) && !defined(_STANDALONE)
10554230938Sws if (!_cachelinesize)
10654230938Sws getcachelinesize();
10754230938Sws #endif
1084c434f62Seeh
1094c434f62Seeh if (CACHEINFO.dcache_size > 0) {
1104c434f62Seeh linesz = CACHEINFO.dcache_line_size;
11112810ed3Smatt off = (uintptr_t)from & (linesz - 1);
11212810ed3Smatt l = (len + off + linesz - 1) & ~(linesz - 1);
11354230938Sws p = (char *)from - off;
11454230938Sws do {
1154a2c5841Sperry __asm volatile ("dcbst 0,%0" :: "r"(p));
1164c434f62Seeh p += linesz;
11712810ed3Smatt } while ((l -= linesz) != 0);
1184c434f62Seeh }
1194a2c5841Sperry __asm volatile ("sync");
1204c434f62Seeh
1214c434f62Seeh if (CACHEINFO.icache_size > 0 ) {
1224c434f62Seeh linesz = CACHEINFO.icache_line_size;
12312810ed3Smatt off = (uintptr_t)from & (linesz - 1);
12412810ed3Smatt l = (len + off + linesz - 1) & ~(linesz - 1);
12554230938Sws p = (char *)from - off;
12654230938Sws do {
1274a2c5841Sperry __asm volatile ("icbi 0,%0" :: "r"(p));
1284c434f62Seeh p += linesz;
12912810ed3Smatt } while ((l -= linesz) != 0);
1304c434f62Seeh }
1314a2c5841Sperry __asm volatile ("sync; isync");
13254230938Sws }
133