]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/sparc64/sparc64/cheetah.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / sparc64 / sparc64 / cheetah.c
1 /*-
2  * Copyright (c) 2003 Jake Burkholder.
3  * Copyright (c) 2005, 2008, 2010 Marius Strobl <marius@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include "opt_pmap.h"
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/lock.h>
36 #include <sys/mutex.h>
37 #include <sys/smp.h>
38
39 #include <vm/vm.h>
40 #include <vm/pmap.h>
41
42 #include <machine/asi.h>
43 #include <machine/cache.h>
44 #include <machine/cpu.h>
45 #include <machine/cpufunc.h>
46 #include <machine/dcr.h>
47 #include <machine/lsu.h>
48 #include <machine/mcntl.h>
49 #include <machine/smp.h>
50 #include <machine/tlb.h>
51 #include <machine/ver.h>
52 #include <machine/vmparam.h>
53
54 #define CHEETAH_ICACHE_TAG_LOWER        0x30
55
56 /*
57  * CPU-specific initialization - this is used for both the Sun Cheetah and
58  * later as well as the Fujitsu Zeus and later CPUs.
59  */
60 void
61 cheetah_init(u_int cpu_impl)
62 {
63         u_long val;
64
65         /* Ensure the TSB Extension Registers hold 0 as TSB_Base. */
66
67         stxa(AA_DMMU_TSB_PEXT_REG, ASI_DMMU, 0);
68         stxa(AA_IMMU_TSB_PEXT_REG, ASI_IMMU, 0);
69         membar(Sync);
70
71         stxa(AA_DMMU_TSB_SEXT_REG, ASI_DMMU, 0);
72         /*
73          * NB: the secondary context was removed from the iMMU.
74          */
75         membar(Sync);
76
77         stxa(AA_DMMU_TSB_NEXT_REG, ASI_DMMU, 0);
78         stxa(AA_IMMU_TSB_NEXT_REG, ASI_IMMU, 0);
79         membar(Sync);
80
81         if (cpu_impl == CPU_IMPL_SPARC64V) {
82                 /* Ensure MCNTL_JPS1_TSBP is 0. */
83                 val = ldxa(AA_MCNTL, ASI_MCNTL);
84                 val &= ~MCNTL_JPS1_TSBP;
85                 stxa(AA_MCNTL, ASI_MCNTL, val);
86                 return;
87         }
88
89         /*
90          * Configure the first large dTLB to hold 4MB pages (e.g. for direct
91          * mappings) for all three contexts and ensure the second one is set
92          * up to hold 8k pages for them.  Note that this is constraint by
93          * US-IV+, whose large dTLBs can only hold entries of certain page
94          * sizes each.
95          * For US-IV+, additionally ensure that the large iTLB is set up to
96          * hold 8k pages for nucleus and primary context (still no secondary
97          * iMMU context.
98          * NB: according to documentation, changing the page size of the same
99          * context requires a context demap before changing the corresponding
100          * page size, but we hardly can flush our locked pages here, so we use
101          * a demap all instead.
102          */
103         stxa(TLB_DEMAP_ALL, ASI_DMMU_DEMAP, 0);
104         membar(Sync);
105         val = (TS_4M << TLB_PCXR_N_PGSZ0_SHIFT) |
106             (TS_8K << TLB_PCXR_N_PGSZ1_SHIFT) |
107             (TS_4M << TLB_PCXR_P_PGSZ0_SHIFT) |
108             (TS_8K << TLB_PCXR_P_PGSZ1_SHIFT);
109         if (cpu_impl == CPU_IMPL_ULTRASPARCIVp)
110                 val |= (TS_8K << TLB_PCXR_N_PGSZ_I_SHIFT) |
111                     (TS_8K << TLB_PCXR_P_PGSZ_I_SHIFT);
112         stxa(AA_DMMU_PCXR, ASI_DMMU, val);
113         val = (TS_4M << TLB_SCXR_S_PGSZ0_SHIFT) |
114             (TS_8K << TLB_SCXR_S_PGSZ1_SHIFT);
115         stxa(AA_DMMU_SCXR, ASI_DMMU, val);
116         flush(KERNBASE);
117
118         /*
119          * Ensure DCR_IFPOE is disabled as long as we haven't implemented
120          * support for it (if ever) as most if not all firmware versions
121          * apparently turn it on.  Not making use of DCR_IFPOE should also
122          * avoid Cheetah erratum #109.
123          */
124         val = rd(asr18) & ~DCR_IFPOE;
125         if (cpu_impl == CPU_IMPL_ULTRASPARCIVp) {
126                 /*
127                  * Ensure the branch prediction mode is set to PC indexing
128                  * in order to work around US-IV+ erratum #2.
129                  */
130                 val = (val & ~DCR_BPM_MASK) | DCR_BPM_PC;
131                 /*
132                  * XXX disable dTLB parity error reporting as otherwise we
133                  * get seemingly false positives when copying in the user
134                  * window by simulating a fill trap on return to usermode in
135                  * case single issue is disabled, which thus appears to be
136                  * a CPU bug.
137                  */
138                 val &= ~DCR_DTPE;
139         }
140         wr(asr18, val, 0);
141 }
142
143 /*
144  * Enable level 1 caches.
145  */
146 void
147 cheetah_cache_enable(u_int cpu_impl)
148 {
149         u_long lsu;
150
151         lsu = ldxa(0, ASI_LSU_CTL_REG);
152         if (cpu_impl == CPU_IMPL_ULTRASPARCIII) {
153                 /* Disable P$ due to US-III erratum #18. */
154                 lsu &= ~LSU_PE;
155         }
156         stxa(0, ASI_LSU_CTL_REG, lsu | LSU_IC | LSU_DC);
157         flush(KERNBASE);
158 }
159
160 /*
161  * Flush all lines from the level 1 caches.
162  */
163 void
164 cheetah_cache_flush(void)
165 {
166         u_long addr, lsu;
167         register_t s;
168
169         s = intr_disable();
170         for (addr = 0; addr < PCPU_GET(cache.dc_size);
171             addr += PCPU_GET(cache.dc_linesize))
172                 /*
173                  * Note that US-IV+ additionally require a membar #Sync before
174                  * a load or store to ASI_DCACHE_TAG.
175                  */
176                 __asm __volatile(
177                     "membar #Sync;"
178                     "stxa %%g0, [%0] %1;"
179                     "membar #Sync"
180                     : : "r" (addr), "n" (ASI_DCACHE_TAG));
181
182         /* The I$ must be disabled when flushing it so ensure it's off. */
183         lsu = ldxa(0, ASI_LSU_CTL_REG);
184         stxa(0, ASI_LSU_CTL_REG, lsu & ~(LSU_IC));
185         flush(KERNBASE);
186         for (addr = CHEETAH_ICACHE_TAG_LOWER;
187             addr < PCPU_GET(cache.ic_size) * 2;
188             addr += PCPU_GET(cache.ic_linesize) * 2)
189                 __asm __volatile(
190                     "stxa %%g0, [%0] %1;"
191                     "membar #Sync"
192                     : : "r" (addr), "n" (ASI_ICACHE_TAG));
193         stxa(0, ASI_LSU_CTL_REG, lsu);
194         flush(KERNBASE);
195         intr_restore(s);
196 }
197
198 /*
199  * Flush a physical page from the data cache.
200  */
201 void
202 cheetah_dcache_page_inval(vm_paddr_t spa)
203 {
204         vm_paddr_t pa;
205         void *cookie;
206
207         KASSERT((spa & PAGE_MASK) == 0,
208             ("%s: pa not page aligned", __func__));
209         cookie = ipi_dcache_page_inval(tl_ipi_cheetah_dcache_page_inval, spa);
210         for (pa = spa; pa < spa + PAGE_SIZE;
211             pa += PCPU_GET(cache.dc_linesize))
212                 stxa_sync(pa, ASI_DCACHE_INVALIDATE, 0);
213         ipi_wait(cookie);
214 }
215
216 /*
217  * Flush a physical page from the intsruction cache.  Instruction cache
218  * consistency is maintained by hardware.
219  */
220 void
221 cheetah_icache_page_inval(vm_paddr_t pa __unused)
222 {
223
224 }
225
226 #define cheetah_dmap_all() do {                                         \
227         stxa(TLB_DEMAP_ALL, ASI_DMMU_DEMAP, 0);                         \
228         stxa(TLB_DEMAP_ALL, ASI_IMMU_DEMAP, 0);                         \
229         flush(KERNBASE);                                                \
230 } while (0)
231
232 /*
233  * Flush all non-locked mappings from the TLB.
234  */
235 void
236 cheetah_tlb_flush_nonlocked(void)
237 {
238
239         cheetah_dmap_all();
240 }
241
242 /*
243  * Flush all user mappings from the TLB.
244  */
245 void
246 cheetah_tlb_flush_user()
247 {
248
249         /*
250          * Just use cheetah_dmap_all() and accept somes TLB misses
251          * rather than searching all 1040 D-TLB and 144 I-TLB slots
252          * for non-kernel mappings.
253          */
254         cheetah_dmap_all();
255 }