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