]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/sun4v/sun4v/tsb.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / sun4v / sun4v / tsb.c
1 /*-
2  * Copyright (c) 2006 Kip Macy
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30
31 #include "opt_ddb.h"
32 #include "opt_pmap.h"
33
34 #include <sys/param.h>
35 #include <sys/queue.h>
36 #include <sys/ktr.h>
37 #include <sys/lock.h>
38 #include <sys/mutex.h>
39 #include <sys/smp.h>
40 #include <sys/sysctl.h>
41 #include <sys/systm.h>
42
43 #include <vm/vm.h> 
44 #include <vm/vm_extern.h> 
45 #include <vm/vm_page.h>
46 #include <vm/vm_pageout.h>
47
48 #include <machine/cpufunc.h>
49 #include <machine/hypervisorvar.h>
50 #include <machine/smp.h>
51 #include <machine/mmu.h>
52 #include <machine/tte.h>
53 #include <machine/tte_hash.h>
54 #include <machine/tsb.h>
55 #include <machine/vmparam.h>
56 #include <machine/tlb.h>
57
58 CTASSERT(sizeof(tte_t) == sizeof(uint64_t));
59 #define TSB_MASK(tsb) ((tsb->hti_ntte) - 1)
60 /* make TSB start off at the same size as the hash */
61 #define TSB_SIZE       8
62
63 #ifdef DEBUG_TSB
64 #define DPRINTF printf
65 #else
66 #define DPRINTF(...)
67 #endif
68
69 void tsb_sysinit(void);
70
71 void
72 tsb_init(hv_tsb_info_t *hvtsb, uint64_t *scratchval, uint64_t page_shift)
73 {
74         void *ptr;
75         int npages = (1 << page_shift);
76
77         ptr = pmap_alloc_zeroed_contig_pages(npages, npages*PAGE_SIZE);
78         
79         if ((((uint64_t)ptr) & (npages*PAGE_SIZE - 1)) != 0)
80                 panic("vm_page_alloc_contig allocated unaligned pages: %p",
81                       ptr);
82         
83         hvtsb->hti_idxpgsz = TTE8K;
84         hvtsb->hti_assoc = 1;
85         hvtsb->hti_ntte = (npages*PAGE_SIZE >> TTE_SHIFT);
86         hvtsb->hti_ctx_index = -1;    /* TSBs aren't shared so if we don't 
87                                          * set the context in the TTEs we can 
88                                          * simplify miss handling slightly
89                                          */
90         hvtsb->hti_pgszs = TSB8K;
91         hvtsb->hti_rsvd = 0;
92         hvtsb->hti_ra = TLB_DIRECT_TO_PHYS((vm_offset_t)ptr);
93
94         *scratchval = ((uint64_t) ptr) | page_shift;
95 }
96
97 void
98 tsb_deinit(hv_tsb_info_t *hvtsb)
99 {
100         vm_page_t m, tm;
101         int i;
102         
103
104         m = PHYS_TO_VM_PAGE((vm_paddr_t)hvtsb->hti_ra);
105         for (i = 0, tm = m; i < TSB_SIZE; i++, m++) {
106                 tm->wire_count--;
107                 atomic_subtract_int(&cnt.v_wire_count, 1);
108                 vm_page_free(tm);
109         }
110 }
111
112
113 void
114 tsb_assert_invalid(hv_tsb_info_t *tsb, vm_offset_t va)
115 {
116         vm_paddr_t tsb_load_pa;
117         uint64_t tsb_index, tsb_shift, tte_tag, tte_data;
118         tsb_shift = TTE_PAGE_SHIFT(tsb->hti_idxpgsz);
119         tsb_index = (va >> tsb_shift) & TSB_MASK(tsb);
120         tsb_load_pa = tsb->hti_ra + 2*tsb_index*sizeof(uint64_t);
121         load_real_dw(tsb_load_pa, &tte_tag, &tte_data);
122         if (tte_tag == 0 && tte_data == 0)
123                 return;
124         printf("tsb_shift=0x%lx tsb_index=0x%lx\n", tsb_shift, tsb_index);
125         printf("tte_tag=0x%lx tte_data=0x%lx TSB_MASK=%lx\n", tte_tag, tte_data, (uint64_t)TSB_MASK(tsb));
126         panic("non-zero entry found where not expected");
127
128 }
129
130 void 
131 tsb_set_tte_real(hv_tsb_info_t *tsb, vm_offset_t index_va, vm_offset_t tag_va, 
132                  uint64_t tte_data, uint64_t ctx)
133 {
134         vm_paddr_t tsb_store_pa;
135         uint64_t tsb_index, tsb_shift, tte_tag;
136         DPRINTF("tsb_set_tte index_va: 0x%lx tag_va: 0x%lx idxpgsz: %x ", 
137                 index_va, tag_va, tsb->hti_idxpgsz);
138
139         tsb_shift = TTE_PAGE_SHIFT(tsb->hti_idxpgsz);
140
141         tsb_index = (index_va >> tsb_shift) & TSB_MASK(tsb);
142         DPRINTF("tsb_index_absolute: 0x%lx tsb_index: 0x%lx\n", (index_va >> tsb_shift), tsb_index);
143         tsb_store_pa = tsb->hti_ra + 2*tsb_index*sizeof(uint64_t);
144
145         /* store new value with valid bit cleared 
146          * to avoid invalid intermediate value;
147          */
148         store_real(tsb_store_pa + sizeof(uint64_t), tte_data);
149         tte_tag = (ctx << TTARGET_CTX_SHIFT) | (tag_va >> TTARGET_VA_SHIFT);
150         store_real(tsb_store_pa, tte_tag);
151
152
153
154 void 
155 tsb_set_tte(hv_tsb_info_t *tsb, vm_offset_t va, uint64_t tte_data, uint64_t ctx)
156 {
157
158         uint64_t tsb_index, tsb_shift, tte_tag;
159         tte_t *entry;
160
161         tsb_shift = TTE_PAGE_SHIFT(tsb->hti_idxpgsz);
162         tsb_index = (va >> tsb_shift) & TSB_MASK(tsb);
163         entry = (tte_t *)TLB_PHYS_TO_DIRECT(tsb->hti_ra + 2*tsb_index*sizeof(uint64_t));
164         tte_tag = (ctx << TTARGET_CTX_SHIFT) | (va >> TTARGET_VA_SHIFT);
165         /* store new value with valid bit cleared 
166          * to avoid invalid intermediate value;
167          */
168         *(entry + 1) = 0;
169         membar(StoreLoad);
170         *(entry) = tte_tag;
171         *(entry + 1) = tte_data;
172         membar(Sync);
173
174
175
176 void 
177 tsb_clear(hv_tsb_info_t *tsb)
178 {
179         hwblkclr((void *)TLB_PHYS_TO_DIRECT(tsb->hti_ra), tsb->hti_ntte << TTE_SHIFT);
180 }
181
182 void 
183 tsb_clear_tte(hv_tsb_info_t *tsb, vm_offset_t va)
184 {
185         tte_t *entry;
186         uint64_t tsb_index, tsb_shift;
187
188         tsb_shift = TTE_PAGE_SHIFT(tsb->hti_idxpgsz);
189         tsb_index = (va >> tsb_shift) & TSB_MASK(tsb);
190         entry = (tte_t *)TLB_PHYS_TO_DIRECT(tsb->hti_ra + 2*tsb_index*sizeof(uint64_t));
191         
192         *(entry + 1) = 0;
193
194         membar(Sync);
195 }
196
197 void
198 tsb_clear_range(hv_tsb_info_t *tsb, vm_offset_t sva, vm_offset_t eva)
199 {
200         vm_offset_t tva;
201         uint64_t tsb_index, tsb_shift, tsb_mask;
202         tte_t *entry;
203
204         tsb_mask = TSB_MASK(tsb);
205         tsb_shift = TTE_PAGE_SHIFT(tsb->hti_idxpgsz);
206
207         for (tva = sva; tva < eva; tva += PAGE_SIZE) {
208                 tsb_index = (tva >> tsb_shift) & tsb_mask;
209                 entry = (tte_t *)TLB_PHYS_TO_DIRECT(tsb->hti_ra + 2*tsb_index*sizeof(uint64_t));
210                 *(entry + 1) = 0;
211         }
212
213         membar(Sync);
214 }
215
216 tte_t
217 tsb_get_tte(hv_tsb_info_t *tsb, vm_offset_t va)
218 {
219         tte_t *entry;
220         uint64_t tsb_index, tsb_shift, tte_tag, tte_data;
221
222         tsb_shift = TTE_PAGE_SHIFT(tsb->hti_idxpgsz);
223         tsb_index = (va >> tsb_shift) & TSB_MASK(tsb);
224         entry = (tte_t *)TLB_PHYS_TO_DIRECT(tsb->hti_ra + 2*tsb_index*sizeof(uint64_t));
225         tte_tag = *(entry);
226         tte_data = *(entry + 1);
227
228         if ((tte_tag << TTARGET_VA_SHIFT) == (va & ~PAGE_MASK_4M))
229                 return tte_data;
230
231         return (0UL);
232 }
233
234 tte_t
235 tsb_lookup_tte(vm_offset_t va, uint64_t ctx)
236 {
237         tte_t tte_data;
238
239         tte_data = 0;
240
241         if ((tte_data = tsb_get_tte(&kernel_td[TSB4M_INDEX], va)) != 0)
242                 goto done;
243
244         /*
245          * handle user data 
246          */
247 done:
248         return tte_data;
249 }
250
251 uint64_t
252 tsb_set_scratchpad_kernel(hv_tsb_info_t *tsb)
253 {
254         uint64_t tsb_shift, tsb_scratch;
255         tsb_shift = ffs(tsb->hti_ntte >> (PAGE_SHIFT - TTE_SHIFT)) - 1;
256         tsb_scratch = TLB_PHYS_TO_DIRECT(tsb->hti_ra) | tsb_shift;
257         
258         set_tsb_kernel_scratchpad(tsb_scratch);
259         membar(Sync);
260         return tsb_scratch;
261 }
262
263 uint64_t
264 tsb_set_scratchpad_user(hv_tsb_info_t *tsb)
265 {
266         uint64_t tsb_shift, tsb_scratch;
267         tsb_shift = ffs(tsb->hti_ntte >> (PAGE_SHIFT - TTE_SHIFT)) - 1;
268         tsb_scratch = TLB_PHYS_TO_DIRECT(tsb->hti_ra) | tsb_shift;
269         set_tsb_user_scratchpad(tsb_scratch);
270         membar(Sync);
271         return tsb_scratch;
272 }
273
274 int
275 tsb_size(hv_tsb_info_t *hvtsb)
276 {
277         return (hvtsb->hti_ntte >> (PAGE_SHIFT - TTE_SHIFT));
278 }
279
280 int
281 tsb_page_shift(pmap_t pmap)
282 {
283         return (pmap->pm_tsbscratch & PAGE_MASK);
284 }