xref: /netbsd-src/lib/libc/arch/powerpc64/gen/syncicache.c (revision bbd1e49222699ea994d06ab0cd4a0e8abca29549)
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