BSD 4_4 release
[unix-history] / usr / src / sys / sparc / sparc / cache.c
CommitLineData
fe0b6a77 1/*
ad787160
C
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
fe0b6a77
CT
4 *
5 * This software was developed by the Computer Systems Engineering group
6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7 * contributed to Berkeley.
8 *
b480239a
KB
9 * All advertising materials mentioning features or use of this software
10 * must display the following acknowledgement:
11 * This product includes software developed by the University of
0067b0bc 12 * California, Lawrence Berkeley Laboratory.
b480239a 13 *
ad787160
C
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the University of
25 * California, Berkeley and its contributors.
26 * 4. Neither the name of the University nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
fe0b6a77 41 *
ad787160 42 * @(#)cache.c 8.1 (Berkeley) 7/19/93
fe0b6a77 43 *
ad787160 44 * from: $Header: cache.c,v 1.10 93/07/18 06:23:51 torek Exp $ (LBL)
fe0b6a77
CT
45 */
46
47/*
48 * Cache routines.
8736a173
CT
49 *
50 * TODO:
8736a173 51 * - rework range flush
fe0b6a77
CT
52 */
53
5548a02f 54#include <sys/param.h>
fe0b6a77 55
0067b0bc 56#include <machine/ctlreg.h>
5548a02f 57#include <machine/pte.h>
fe0b6a77 58
5548a02f
KB
59#include <sparc/sparc/asm.h>
60#include <sparc/sparc/cache.h>
fe0b6a77
CT
61
62enum vactype vactype;
8736a173 63struct cachestats cachestats;
fe0b6a77
CT
64
65/*
66 * Enable the cache.
67 * We need to clear out the valid bits first.
68 */
69void
70cache_enable()
71{
ad787160 72 register u_int i, lim, ls;
fe0b6a77 73
8736a173
CT
74 i = AC_CACHETAGS;
75 lim = i + cacheinfo.c_totalsize;
76 ls = cacheinfo.c_linesize;
77 for (; i < lim; i += ls)
fe0b6a77
CT
78 sta(i, ASI_CONTROL, 0);
79
fe0b6a77
CT
80 stba(AC_SYSENABLE, ASI_CONTROL,
81 lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_CACHE);
8736a173 82 cacheinfo.c_enabled = 1;
fe0b6a77
CT
83 printf("cache enabled\n");
84}
85
86
87/*
88 * Flush the current context from the cache.
89 *
90 * This is done by writing to each cache line in the `flush context'
f4056f14
CT
91 * address space (or, for hardware flush, once to each page in the
92 * hardware flush space, for all cache pages).
fe0b6a77
CT
93 */
94void
95cache_flush_context()
96{
8736a173 97 register char *p;
f4056f14 98 register int i, ls;
fe0b6a77 99
8736a173 100 cachestats.cs_ncxflush++;
f4056f14
CT
101 p = (char *)0; /* addresses 0..cacheinfo.c_totalsize will do fine */
102 if (cacheinfo.c_hwflush) {
103 ls = NBPG;
104 i = cacheinfo.c_totalsize >> PGSHIFT;
105 for (; --i >= 0; p += ls)
106 sta(p, ASI_HWFLUSHCTX, 0);
107 } else {
108 ls = cacheinfo.c_linesize;
109 i = cacheinfo.c_totalsize >> cacheinfo.c_l2linesize;
110 for (; --i >= 0; p += ls)
111 sta(p, ASI_FLUSHCTX, 0);
112 }
fe0b6a77
CT
113}
114
115/*
116 * Flush the given virtual segment from the cache.
117 *
118 * This is also done by writing to each cache line, except that
119 * now the addresses must include the virtual segment number, and
120 * we use the `flush segment' space.
f4056f14
CT
121 *
122 * Again, for hardware, we just write each page (in hw-flush space).
fe0b6a77
CT
123 */
124void
125cache_flush_segment(vseg)
126 register int vseg;
127{
8736a173
CT
128 register int i, ls;
129 register char *p;
fe0b6a77 130
8736a173 131 cachestats.cs_nsgflush++;
f4056f14
CT
132 p = (char *)VSTOVA(vseg); /* seg..seg+sz rather than 0..sz */
133 if (cacheinfo.c_hwflush) {
134 ls = NBPG;
135 i = cacheinfo.c_totalsize >> PGSHIFT;
136 for (; --i >= 0; p += ls)
137 sta(p, ASI_HWFLUSHSEG, 0);
138 } else {
139 ls = cacheinfo.c_linesize;
140 i = cacheinfo.c_totalsize >> cacheinfo.c_l2linesize;
141 for (; --i >= 0; p += ls)
142 sta(p, ASI_FLUSHSEG, 0);
143 }
fe0b6a77
CT
144}
145
146/*
147 * Flush the given virtual page from the cache.
148 * (va is the actual address, and must be aligned on a page boundary.)
149 * Again we write to each cache line.
150 */
151void
152cache_flush_page(va)
153 int va;
154{
8736a173
CT
155 register int i, ls;
156 register char *p;
157
158 cachestats.cs_npgflush++;
159 p = (char *)va;
160 if (cacheinfo.c_hwflush)
161 sta(p, ASI_HWFLUSHPG, 0);
162 else {
163 ls = cacheinfo.c_linesize;
164 i = NBPG >> cacheinfo.c_l2linesize;
165 for (; --i >= 0; p += ls)
166 sta(p, ASI_FLUSHPG, 0);
167 }
fe0b6a77
CT
168}
169
170/*
171 * Flush a range of virtual addresses (in the current context).
172 * The first byte is at (base&~PGOFSET) and the last one is just
173 * before byte (base+len).
174 *
175 * We choose the best of (context,segment,page) here.
176 */
177void
178cache_flush(base, len)
179 caddr_t base;
180 register u_int len;
181{
8736a173
CT
182 register int i, ls, baseoff;
183 register char *p;
fe0b6a77
CT
184
185 /*
186 * Figure out how much must be flushed.
187 *
188 * If we need to do 16 pages, we can do a segment in the same
189 * number of loop iterations. We can also do the context. If
190 * we would need to do two segments, do the whole context.
191 * This might not be ideal (e.g., fsck likes to do 65536-byte
192 * reads, which might not necessarily be aligned).
193 *
194 * We could try to be sneaky here and use the direct mapping
195 * to avoid flushing things `below' the start and `above' the
196 * ending address (rather than rounding to whole pages and
197 * segments), but I did not want to debug that now and it is
198 * not clear it would help much.
8736a173
CT
199 *
200 * (XXX the magic number 16 is now wrong, must review policy)
fe0b6a77
CT
201 */
202 baseoff = (int)base & PGOFSET;
203 i = (baseoff + len + PGOFSET) >> PGSHIFT;
8736a173
CT
204
205 cachestats.cs_nraflush++;
206#ifdef notyet
207 cachestats.cs_ra[min(i, MAXCACHERANGE)]++;
208#endif
209
fe0b6a77
CT
210 if (i <= 15) {
211 /* cache_flush_page, for i pages */
8736a173
CT
212 p = (char *)((int)base & ~baseoff);
213 if (cacheinfo.c_hwflush) {
214 for (; --i >= 0; p += NBPG)
215 sta(p, ASI_HWFLUSHPG, 0);
216 } else {
f4056f14 217 ls = cacheinfo.c_linesize;
8736a173
CT
218 i <<= PGSHIFT - cacheinfo.c_l2linesize;
219 for (; --i >= 0; p += ls)
220 sta(p, ASI_FLUSHPG, 0);
221 }
fe0b6a77
CT
222 return;
223 }
224 baseoff = (u_int)base & SGOFSET;
225 i = (baseoff + len + SGOFSET) >> SGSHIFT;
f4056f14
CT
226 if (i == 1)
227 cache_flush_segment(VA_VSEG(base));
228 else
229 cache_flush_context();
fe0b6a77 230}