1139825Simp/*-
286221Stmm * Copyright (c) 1996
386221Stmm *	The President and Fellows of Harvard College. All rights reserved.
486221Stmm * Copyright (c) 1992, 1993
586221Stmm *	The Regents of the University of California.  All rights reserved.
686221Stmm *
786221Stmm * This software was developed by the Computer Systems Engineering group
886221Stmm * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
986221Stmm * contributed to Berkeley.
1086221Stmm *
1186221Stmm * All advertising materials mentioning features or use of this software
1286221Stmm * must display the following acknowledgement:
1386221Stmm *	This product includes software developed by Harvard University.
1486221Stmm *
1586221Stmm * Redistribution and use in source and binary forms, with or without
1686221Stmm * modification, are permitted provided that the following conditions
1786221Stmm * are met:
1886221Stmm *
1986221Stmm * 1. Redistributions of source code must retain the above copyright
2086221Stmm *    notice, this list of conditions and the following disclaimer.
2186221Stmm * 2. Redistributions in binary form must reproduce the above copyright
2286221Stmm *    notice, this list of conditions and the following disclaimer in the
2386221Stmm *    documentation and/or other materials provided with the distribution.
2486221Stmm * 3. All advertising materials mentioning features or use of this software
2586221Stmm *    must display the following acknowledgement:
2686221Stmm *	This product includes software developed by Aaron Brown and
2786221Stmm *	Harvard University.
2886221Stmm * 4. Neither the name of the University nor the names of its contributors
2986221Stmm *    may be used to endorse or promote products derived from this software
3086221Stmm *    without specific prior written permission.
3186221Stmm *
3286221Stmm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
3386221Stmm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3486221Stmm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3586221Stmm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3686221Stmm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3786221Stmm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3886221Stmm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3986221Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4086221Stmm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4186221Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4286221Stmm * SUCH DAMAGE.
4386221Stmm */
4486221Stmm/*-
4586221Stmm * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
46204153Smarius * Copyright (c) 2008, 2010 Marius Strobl <marius@FreeBSD.org>
4786221Stmm * All rights reserved.
4886221Stmm *
4986221Stmm * Redistribution and use in source and binary forms, with or without
5086221Stmm * modification, are permitted provided that the following conditions
5186221Stmm * are met:
5286221Stmm * 1. Redistributions of source code must retain the above copyright
5386221Stmm *    notice, this list of conditions and the following disclaimer.
5486221Stmm * 2. Redistributions in binary form must reproduce the above copyright
5586221Stmm *    notice, this list of conditions and the following disclaimer in the
5686221Stmm *    documentation and/or other materials provided with the distribution.
5786221Stmm *
5886221Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
5986221Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
6086221Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
6186221Stmm * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
6286221Stmm * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6386221Stmm * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
6486221Stmm * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
6586221Stmm * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
6686221Stmm * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
6786221Stmm * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6886221Stmm *
6986221Stmm *	from: @(#)cache.c	8.2 (Berkeley) 10/30/93
7086221Stmm *	from: NetBSD: cache.c,v 1.5 2000/12/06 01:47:50 mrg Exp
7186221Stmm */
7286221Stmm
73176994Smarius#include <sys/cdefs.h>
74176994Smarius__FBSDID("$FreeBSD$");
75176994Smarius
7686221Stmm#include <sys/param.h>
7786221Stmm#include <sys/systm.h>
78182689Smarius#include <sys/pcpu.h>
7986221Stmm
80112399Sjake#include <dev/ofw/openfirm.h>
8186221Stmm
8286221Stmm#include <machine/cache.h>
83113453Sjake#include <machine/tlb.h>
8490620Stmm#include <machine/ver.h>
8586221Stmm
86122464Sjakecache_enable_t *cache_enable;
87122464Sjakecache_flush_t *cache_flush;
88112399Sjakedcache_page_inval_t *dcache_page_inval;
89112399Sjakeicache_page_inval_t *icache_page_inval;
90101119Sjake
91211049Smariusu_int dcache_color_ignore;
92211049Smarius
9386221Stmm#define	OF_GET(h, n, v)	OF_getprop((h), (n), &(v), sizeof(v))
9486221Stmm
95204153Smariusstatic u_int cache_new_prop(u_int cpu_impl);
96204153Smarius
97204153Smariusstatic u_int
98204153Smariuscache_new_prop(u_int cpu_impl)
99204153Smarius{
100204153Smarius
101204153Smarius	switch (cpu_impl) {
102204153Smarius	case CPU_IMPL_ULTRASPARCIV:
103204153Smarius	case CPU_IMPL_ULTRASPARCIVp:
104204153Smarius		return (1);
105204153Smarius	default:
106204153Smarius		return (0);
107204153Smarius	}
108204153Smarius}
109204153Smarius
11086221Stmm/*
111204153Smarius * Fill in the cache parameters using the CPU node.
11286221Stmm */
11386221Stmmvoid
114182689Smariuscache_init(struct pcpu *pcpu)
11586221Stmm{
11686221Stmm	u_long set;
117204153Smarius	u_int use_new_prop;
11886221Stmm
119211049Smarius	/*
120211049Smarius	 * For CPUs which ignore TD_CV and support hardware unaliasing don't
121211049Smarius	 * bother doing page coloring.  This is equal across all CPUs.
122211049Smarius	 */
123211049Smarius	if (pcpu->pc_cpuid == 0 && pcpu->pc_impl == CPU_IMPL_SPARC64V)
124211049Smarius		dcache_color_ignore = 1;
125211049Smarius
126204153Smarius	use_new_prop = cache_new_prop(pcpu->pc_impl);
127204153Smarius	if (OF_GET(pcpu->pc_node, !use_new_prop ? "icache-size" :
128204153Smarius	    "l1-icache-size", pcpu->pc_cache.ic_size) == -1 ||
129204153Smarius	    OF_GET(pcpu->pc_node, !use_new_prop ? "icache-line-size" :
130204153Smarius	    "l1-icache-line-size", pcpu->pc_cache.ic_linesize) == -1 ||
131204153Smarius	    OF_GET(pcpu->pc_node, !use_new_prop ? "icache-associativity" :
132204153Smarius	    "l1-icache-associativity", pcpu->pc_cache.ic_assoc) == -1 ||
133204153Smarius	    OF_GET(pcpu->pc_node, !use_new_prop ? "dcache-size" :
134204153Smarius	    "l1-dcache-size", pcpu->pc_cache.dc_size) == -1 ||
135204153Smarius	    OF_GET(pcpu->pc_node, !use_new_prop ? "dcache-line-size" :
136204153Smarius	    "l1-dcache-line-size", pcpu->pc_cache.dc_linesize) == -1 ||
137204153Smarius	    OF_GET(pcpu->pc_node, !use_new_prop ? "dcache-associativity" :
138204153Smarius	    "l1-dcache-associativity", pcpu->pc_cache.dc_assoc) == -1 ||
139204153Smarius	    OF_GET(pcpu->pc_node, !use_new_prop ? "ecache-size" :
140204153Smarius	    "l2-cache-size", pcpu->pc_cache.ec_size) == -1 ||
141204153Smarius	    OF_GET(pcpu->pc_node, !use_new_prop ? "ecache-line-size" :
142204153Smarius	    "l2-cache-line-size", pcpu->pc_cache.ec_linesize) == -1 ||
143204153Smarius	    OF_GET(pcpu->pc_node, !use_new_prop ? "ecache-associativity" :
144204153Smarius	    "l2-cache-associativity", pcpu->pc_cache.ec_assoc) == -1)
145230633Smarius		OF_panic("%s: could not retrieve cache parameters", __func__);
14686221Stmm
147182689Smarius	set = pcpu->pc_cache.ic_size / pcpu->pc_cache.ic_assoc;
148182689Smarius	if ((set & ~(1UL << (ffs(set) - 1))) != 0)
149230633Smarius		OF_panic("%s: I$ set size not a power of 2", __func__);
150182689Smarius	if ((pcpu->pc_cache.dc_size &
151182689Smarius	    ~(1UL << (ffs(pcpu->pc_cache.dc_size) - 1))) != 0)
152230633Smarius		OF_panic("%s: D$ size not a power of 2", __func__);
153207537Smarius	/*
154207537Smarius	 * For CPUs which don't support unaliasing in hardware ensure that
155207537Smarius	 * the data cache doesn't have too many virtual colors.
156207537Smarius	 */
157211049Smarius	if (dcache_color_ignore == 0 && ((pcpu->pc_cache.dc_size /
158211049Smarius	    pcpu->pc_cache.dc_assoc) / PAGE_SIZE) != DCACHE_COLORS)
159230633Smarius		OF_panic("%s: too many D$ colors", __func__);
160182689Smarius	set = pcpu->pc_cache.ec_size / pcpu->pc_cache.ec_assoc;
161182689Smarius	if ((set & ~(1UL << (ffs(set) - 1))) != 0)
162230633Smarius		OF_panic("%s: E$ set size not a power of 2", __func__);
16386221Stmm
164204152Smarius	if (pcpu->pc_impl >= CPU_IMPL_ULTRASPARCIII) {
165122464Sjake		cache_enable = cheetah_cache_enable;
166122464Sjake		cache_flush = cheetah_cache_flush;
167112399Sjake		dcache_page_inval = cheetah_dcache_page_inval;
168112399Sjake		icache_page_inval = cheetah_icache_page_inval;
169176994Smarius		tlb_flush_nonlocked = cheetah_tlb_flush_nonlocked;
170113453Sjake		tlb_flush_user = cheetah_tlb_flush_user;
171207537Smarius	} else if (pcpu->pc_impl == CPU_IMPL_SPARC64V) {
172223719Smarius		cache_enable = zeus_cache_enable;
173207537Smarius		cache_flush = zeus_cache_flush;
174207537Smarius		dcache_page_inval = zeus_dcache_page_inval;
175207537Smarius		icache_page_inval = zeus_icache_page_inval;
176223719Smarius		tlb_flush_nonlocked = zeus_tlb_flush_nonlocked;
177223719Smarius		tlb_flush_user = zeus_tlb_flush_user;
178207537Smarius	} else if (pcpu->pc_impl >= CPU_IMPL_ULTRASPARCI &&
179207537Smarius	    pcpu->pc_impl < CPU_IMPL_ULTRASPARCIII) {
180122464Sjake		cache_enable = spitfire_cache_enable;
181122464Sjake		cache_flush = spitfire_cache_flush;
182112399Sjake		dcache_page_inval = spitfire_dcache_page_inval;
183112399Sjake		icache_page_inval = spitfire_icache_page_inval;
184176994Smarius		tlb_flush_nonlocked = spitfire_tlb_flush_nonlocked;
185113453Sjake		tlb_flush_user = spitfire_tlb_flush_user;
186207537Smarius	} else
187230633Smarius		OF_panic("%s: unknown CPU", __func__);
18897001Sjake}
189