xref: /netbsd/sys/lib/libkern/arch/powerpc/syncicache.c (revision 0db6a6b0)
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