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