1*0db6a6b0She /* $NetBSD: syncicache.c,v 1.15 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)
35cb9a32fdStsubai #include <sys/time.h>
3654230938Sws #include <sys/proc.h>
376b9ed411Smrg #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
45bc403009Seeh
46bc403009Seeh #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 = {
51bc403009Seeh CACHELINESIZE,
52bc403009Seeh CACHELINESIZE,
53bc403009Seeh CACHELINESIZE,
54bc403009Seeh CACHELINESIZE
55bc403009Seeh };
56bc403009Seeh #define CACHEINFO _cache_info
57bc403009Seeh #elif defined(_KERNEL)
58bc403009Seeh #define CACHEINFO (curcpu()->ci_ci)
5954230938Sws #else
6006edae0fSthorpej #include <stdlib.h>
6106edae0fSthorpej
624907369aSmatt size_t __getcachelinesize (void);
63cb9a32fdStsubai
64bc403009Seeh static int _cachelinesize = 0;
65bc403009Seeh
66bc403009Seeh static struct cache_info _cache_info;
67bc403009Seeh #define CACHEINFO _cache_info
6854230938Sws
694907369aSmatt size_t
__getcachelinesize(void)704907369aSmatt __getcachelinesize(void)
7154230938Sws {
7254230938Sws static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE };
73bc403009Seeh static int cacheinfomib[] = { CTL_MACHDEP, CPU_CACHEINFO };
74bc403009Seeh size_t clen = sizeof(_cache_info);
7554230938Sws
764907369aSmatt if (_cachelinesize)
774907369aSmatt return _cachelinesize;
784907369aSmatt
79bc403009Seeh if (sysctl(cacheinfomib, sizeof(cacheinfomib) / sizeof(cacheinfomib[0]),
80bc403009Seeh &_cache_info, &clen, NULL, 0) == 0) {
81bc403009Seeh _cachelinesize = _cache_info.dcache_line_size;
824907369aSmatt return _cachelinesize;
83bc403009Seeh }
84bc403009Seeh
85bc403009Seeh /* Try older deprecated sysctl */
86bc403009Seeh clen = sizeof(_cachelinesize);
8754230938Sws if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]),
8854230938Sws &_cachelinesize, &clen, NULL, 0) < 0
8954230938Sws || !_cachelinesize)
9054230938Sws abort();
91bc403009Seeh
92bc403009Seeh _cache_info.dcache_size = _cachelinesize;
93bc403009Seeh _cache_info.dcache_line_size = _cachelinesize;
94bc403009Seeh _cache_info.icache_size = _cachelinesize;
95bc403009Seeh _cache_info.icache_line_size = _cachelinesize;
964907369aSmatt
97bc403009Seeh /* If there is no cache, indicate we have issued the sysctl. */
984907369aSmatt if (!_cachelinesize)
994907369aSmatt _cachelinesize = 1;
1004907369aSmatt
1014907369aSmatt return _cachelinesize;
10254230938Sws }
10354230938Sws #endif
10454230938Sws
10554230938Sws void
__syncicache(void * from,size_t len)10612810ed3Smatt __syncicache(void *from, size_t len)
10754230938Sws {
10812810ed3Smatt size_t l, off;
10912810ed3Smatt size_t linesz;
11054230938Sws char *p;
11154230938Sws
11254230938Sws #if !defined(_KERNEL) && !defined(_STANDALONE)
11354230938Sws if (!_cachelinesize)
1144907369aSmatt __getcachelinesize();
11554230938Sws #endif
116bc403009Seeh
117bc403009Seeh if (CACHEINFO.dcache_size > 0) {
118bc403009Seeh linesz = CACHEINFO.dcache_line_size;
11912810ed3Smatt off = (uintptr_t)from & (linesz - 1);
12012810ed3Smatt l = (len + off + linesz - 1) & ~(linesz - 1);
12154230938Sws p = (char *)from - off;
12254230938Sws do {
123ce666bb8Sperry __asm volatile ("dcbst 0,%0" :: "r"(p));
124bc403009Seeh p += linesz;
12512810ed3Smatt } while ((l -= linesz) != 0);
126bc403009Seeh }
127ce666bb8Sperry __asm volatile ("sync");
128bc403009Seeh
129bc403009Seeh if (CACHEINFO.icache_size > 0 ) {
130bc403009Seeh linesz = CACHEINFO.icache_line_size;
13112810ed3Smatt off = (uintptr_t)from & (linesz - 1);
13212810ed3Smatt l = (len + off + linesz - 1) & ~(linesz - 1);
13354230938Sws p = (char *)from - off;
13454230938Sws do {
135ce666bb8Sperry __asm volatile ("icbi 0,%0" :: "r"(p));
136bc403009Seeh p += linesz;
13712810ed3Smatt } while ((l -= linesz) != 0);
138bc403009Seeh }
139ce666bb8Sperry __asm volatile ("sync; isync");
14054230938Sws }
141