Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / cpu / sparc / ultra / mmu.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: mmu.fth
4\
5\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6\
7\ - Do no alter or remove copyright notices
8\
9\ - Redistribution and use of this software in source and binary forms, with
10\ or without modification, are permitted provided that the following
11\ conditions are met:
12\
13\ - Redistribution of source code must retain the above copyright notice,
14\ this list of conditions and the following disclaimer.
15\
16\ - Redistribution in binary form must reproduce the above copyright notice,
17\ this list of conditions and the following disclaimer in the
18\ documentation and/or other materials provided with the distribution.
19\
20\ Neither the name of Sun Microsystems, Inc. or the names of contributors
21\ may be used to endorse or promote products derived from this software
22\ without specific prior written permission.
23\
24\ This software is provided "AS IS," without a warranty of any kind.
25\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
26\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
27\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
28\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
29\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
30\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
31\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
32\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
33\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
34\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
35\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
36\
37\ You acknowledge that this software is not designed, licensed or
38\ intended for use in the design, construction, operation or maintenance of
39\ any nuclear facility.
40\
41\ ========== Copyright Header End ============================================
42id: @(#)mmu.fth 1.32 05/02/16
43purpose:
44copyright: Copyright 2005 Sun Microsystems, Inc. All Rights Reserved
45copyright: Use is subject to license terms.
46
47\ We define this now, until mixed-page support is ready
48[define] MMU-8K-ONLY?
49
50\ Public Interfaces:
51\ pgmap@ ( va -- tte|0 )
52\ pgmap! ( tte virt -- )
53\ set-tte-soft ( tte virt -- tte' )
54\ vpt-walker ( acf -- )
55\ map-page ( pa.lo pa.hi va -- )
56\ unmap-page ( virt -- )
57\ map-pages ( pa.lo pa.hi virtual size -- )
58\ unmap-pages ( va len -- )
59\ >mmu-boundaries ( va len size -- va' len' )
60\ >page-boundaries ( va len -- va' len' )
61
62headerless
63
64#vabits d# 64 = if -1 else 1 #vabits lshift 1- then constant va-mask
65
66pageshift tteshift - constant vptshift
670 1 #vabits pageshift - tteshift + lshift - constant vpt-base
680 vpt-base - constant vpt-size
69
70\ For example, in a 44 bit va space, the vpt-base is at ffff.fffc.0000.0000
71\ The vpt address of a tte mapping any va is found by:
72\ apply va-mask to the va
73\ shift page bits off va (all adrs in same page correspond to same tte)
74\ shift tte bits back on va (each tte is 8 bytes in vpt)
75\ add result to vpt-base
76\
77\ The above method is used to get the tte for both non-vpt and vpt addresses.
78\ The lower pages of the vpt itself are mapped by tte's higher in the vpt.
79\ The next level of pages in the vpt holding tte's for the first level are
80\ themselves mapped by tte's in the vpt-root page at ffff.ffff.ffff.c000.
81\ The vpt-root page is not mapped by a vpt entry, it is locked in the dtlb.
82
83\ These two defers are executed during the performance-critical path
84\ of mapping, but are not re-vectored at run-time. They appear to
85\ be being defined here as DEFERs either to workaround the lack of
86\ forward-definitions, or because their resolutions differ by platform.
87\ Arguably, they should be PATCHed-over where they're resolved...
88
89defer allocate-page ( -- pa.lo pa.hi )
90defer set-tte-soft ( tte virt -- tte' ) ' drop is set-tte-soft
91
92\ This is a code saving measure, it does not obey any of the standard
93\ ABI conventions as it trashes the locals!! Do not call this routine
94\ from outside this file.
95\ On entry:
96\ tos is holding the VA
97\ On exit:
98\ scr = pgmap
99\ sc1 = segment
100\ sc2 = region
101\ sc5 = region-tte
102label pgmap-common
103 va-mask sc1 sc2 setx
104 tos sc2 scr and \ VA & va-mask
105
106 scr pageshift scr srlx \ VA -> vpt offset
107 vpt-base sc1 sc3 setx
108 scr tteshift scr sllx
109 scr sc3 scr add \ pgmap
110
111 scr sc2 sc1 and
112 sc1 pageshift sc1 srlx
113 sc1 tteshift sc1 sllx
114 sc1 sc3 sc1 add \ vpt-segment
115
116 sc1 sc2 sc5 and
117 sc5 pageshift sc2 srlx
118 sc2 tteshift sc2 sllx
119 sc2 sc3 sc2 add \ vpt-region
120
121 retl
122 sc2 %g0 sc5 ldx
123end-code
124
125headers
126
127\ this routine returns 0 for an invalid VA.
128\ the VPT is scanned from region->segment->pgmap before the
129\ access is done.
130code pgmap@ ( va -- tte|0 )
131 pgmap-common call
132 nop \ (delay)
133 \ Validate the region
134 sc5 %g0 %g0 subcc
135 0< if \ region valid?
136 %g0 %g0 tos add \ (delay) Invalid
137
138 \ Validate the segment
139 sc1 %g0 sc5 ldx
140 sc5 %g0 %g0 subcc
141 0< if \ segment valid?
142 %g0 %g0 tos add \ (delay) Invalid
143 scr %g0 tos ldx \ get tte
144 then
145 then
146c;
147
148headerless
149
150\ get vpt address of tte for va
151code >vpt ( va -- adr )
152 va-mask sc1 scr setx
153 tos scr tos and
154 tos pageshift tos srlx
155 vpt-base sc1 scr setx
156 tos tteshift tos sllx
157 tos scr tos add
158c;
159
160\ this routine is the primitive pagemap stuffer.
161\ If it returns 0 then this segment and region are fine.
162\ if the region needs creation then the tte,va,3 and true are returned.
163\ if the segment needs updating then tte,va,2,true are returned
164\ returning non-zero means it required high level assistance.
165code ((pgmap!)) ( tte va -- 0|tte,va,2,-1|tte,va,3,-1 )
166 pgmap-common call
167 nop \ (delay)
168
169 \ Validate the region
170 sc5 %g0 %g0 subcc
171 0>= if \ region valid?
172 %g0 3 sc4 add \ (delay) map-region required.
173 tos sp push
174 sc4 sp push
175 else
176 %g0 1 tos sub \ (delay) map needs assistance
177
178 \ Validate the segment
179 sc1 %g0 sc5 ldx
180 sc5 %g0 %g0 subcc
181 0>= if \ segment valid?
182 %g0 2 sc4 add \ (delay) map-segment required.
183 tos sp push
184 sc4 sp push
185 else
186 %g0 1 tos sub \ (delay) map needs assistance
187
188 \ Pop the tte and stuff the entry
189 sp sc4 pop
190 %g0 %g0 tos add \ All done.
191 sc4 scr %g0 stx \ store the tte.
192 then
193 then
194c;
195
196: (pgmap!) ( tte va -- )
197 recursive ( tte va )
198 ((pgmap!)) if ( tte va index )
199 over swap ( tte va va index )
200 0 ?do >vpt loop ( tte va va' )
201 allocate-page ( tte va va' pa.lo pa.hi )
202 >tte >tte-soft ( tte va va' tte' )
203 swap x! ( tte va )
204 (pgmap!) ( )
205 then
206;
207
208\ From this point onwards we are presenting the higher level MMU routines.
209\ No-one should be calling routines defined before this point - except
210\ pgmap@, and >vpt
211
212headers
213
214: .vpt ( vpt -- )
215 <#
216 u# u# u# u# ascii . hold
217 u# u# u# u# ascii . hold
218 u# u# u# u# ascii . hold
219 u# u# u# u#
220 u#> type
221;
222
223\ root vpt page which is locked in tlb never misses
2240 >vpt >vpt >vpt constant vpt-root
225
226: .vpts ( va -- )
227 pagesize round-down
228 >vpt dup .vpt cr
229 >vpt dup .vpt cr
230 >vpt .vpt cr
231;
232
233headerless
234
235\ NOTE:
236\ The final 2drop is patched at RUNTIME by enable-map-flushing
237\ this code is in a performance path which is why it is not
238\ using a variable/value/defer to switch this feature on/off.
239: (common-mapper) ( va tte len -- )
240 >r swap ( tte va )
241 r@ 0 ?do 2dup i + (pgmap!) pagesize +loop ( tte va )
242 nip r> ( va len )
243 \ patched to flush-tlb-range
244 2drop
245;
246
247headers
248
249\ The virtual memory node calls into this routine to 'modify' entries..
250: pgmap! ( tte virt -- )
251 tuck ( va tte va )
252 set-tte-soft ( va tte' )
253 pagesize (common-mapper) ( )
254;
255
256headerless
257
258\ round pa.lo and va down
259code >tte-boundaries ( pa.lo pa.hi va round -- va pa.lo pa.hi )
260 tos 1 scr sub
261 sp tos pop \ VA
262 tos scr tos andn \ VA'
263 sp sc1 pop
264 sp sc2 pop
265 sc2 scr sc2 andn \ pa.lo'
266 tos sp push
267 sc2 sp push
268 sc1 tos move
269c;
270
271\ round the region to enclose the appropriate page restrictions.
272code >mmu-boundaries ( va len size -- va' len' )
273 sp scr pop \ len
274 sp sc1 pop \ va
275 tos 1 tos sub \ mask
276 sc1 tos sc2 andn \ round-down
277 sc2 sp push
278 scr sc1 scr add \ top VA
279 scr tos scr add \ add size-1
280 scr tos scr andn \ round-down
281 scr sc2 tos sub
282c;
283
284: >page-boundaries ( va len -- va' len' ) pagesize >mmu-boundaries ;
285
286headers
287
288: map-page ( pa.lo pa.hi va -- )
289 pagesize >tte-boundaries ( va' pa.lo' pa.hi )
290 >tte swap pgmap! ( )
291;
292
293headerless
294
295\ this assumes you have correctly aligned all the args!!
296: (map-pages) ( pa.lo pa.hi va len -- )
297 >r pagesize >tte-boundaries ( va pa.lo pa.hi )
298 rot r> ( pa.lo pa.hi va len )
299 bounds ?do ( pa.lo pa.hi )
300 2dup i -rot ( pa.lo pa.hi va pa.lo pa.hi )
301 >tte ( pa.lo pa.hi va tte )
302 over set-tte-soft ( pa.lo pa.hi va tte' )
303 swap (pgmap!) ( pa.lo pa.hi )
304 swap pagesize + swap ( pa.lo' pa.hi )
305 pagesize +loop ( pa.lo' pa.hi )
306 2drop ( )
307;
308
309headers
310
311: unmap-page ( virt -- )
312 dup pgmap@ 0 >tte-valid invert and over pgmap! ( virt )
313 flush-cache-page ( )
314;
315
316headerless
317
318depend-load MMU-8K-ONLY? ${BP}/cpu/sparc/ultra/mmu-policy/8k-pages.fth
319
320headerless
321
322\ Call this once OBPs internal mappings are complete, this will then
323\ enable the tlb flushing code for mapping.
324\ We use patch because this code is all in the performance path.
325: enable-map-flushing ( -- )
326 ['] flush-tlb-range ['] 2drop ( acf1 acf2 )
327 2dup ( acf1 acf2 acf1 acf2 )
328 ['] (common-mapper) (patch ( acf1 acf2 )
329 ['] map-pages (patch ( )
330;
331
332transient
333alias deallocate-segment drop ( vadr -- )
334alias ?allocate-segment drop ( vadr -- )
335resident
336
337headerless
338: (.map) ( vadr tte -- )
339 dup tte>size ( vadr tte size )
340 rot dup ." VA:" .x cr ( tte size vadr )
341 swap 1- and ( tte offset )
342 over .tlb cr ( tte offset )
343 over tte> drop or ( tte padr )
344 swap valid-tte? if ( padr )
345 ." PA:" .x ( )
346 else ( padr )
347 ." Invalid" drop ( )
348 then ( )
349;
350
351\ We set this to change the default translation behaviour so we can
352\ reuse the same vpt-walker for .trans and the translation property.
353\ This defer is set by any map activity; it is critical to performance.
354\ Speeding up the application of IS to a kernel native defer shows up
355\ here as a significant performance win.
356defer vpt-data-fn ( ?? va len tte -- ?? ) ' 3drop is vpt-data-fn
357
358struct
359 /x field >vpt-va
360 /x field >vpt-size
361 /x field >vpt-tte
362constant /prev-vpt-data
363
364/prev-vpt-data ualloc user prev-vpt-data
365
366: vpt-data@ ( -- a b c )
367 prev-vpt-data >r
368 r@ >vpt-va x@
369 r@ >vpt-size x@
370 r> >vpt-tte x@
371;
372: vpt-data! ( a b c -- )
373 prev-vpt-data >r
374 r@ >vpt-tte x!
375 r@ >vpt-size x!
376 r> >vpt-va x!
377;
378
379: prev-tte-invalid ( -- ) 0 prev-vpt-data >vpt-tte x! ;
380: prev-tte-valid? ( -- flag ) prev-vpt-data >vpt-tte x@ valid-tte? ;
381
382: (vpt-pgmap) ( va -- )
383 pagesize bounds do ( )
384 i x@ valid-tte? if ( )
385 i vpt-base - ( offset )
386 vptshift lshift ( va )
387 i x@ dup tte>size swap ( va size tte )
388 2 pick 2 pick 1- and if ( va size tte )
389 \ tte-size overlaps va so we merge
390 3drop ( )
391 else ( va size tte )
392 prev-tte-valid? if ( va size tte )
393 prev-vpt-data >r ( va size tte )
394 2 pick r@ >vpt-va x@ - ( va size tte n )
395 over tte> drop ( va size tte n pa.lo )
396 r@ >vpt-tte x@ tte> drop - ( va size tte n n )
397 = if ( va size tte )
398 \ merge sizes, because va and pa are contiguous.
399 drop nip ( size )
400 r> >vpt-size +! ( )
401 else ( va size tte )
402 2>r >r ( )
403 vpt-data@ vpt-data-fn ( va size tte )
404 r> 2r> vpt-data! ( )
405 r> drop ( )
406 then ( )
407 else ( va size tte )
408 \ save this va,tte for merging
409 vpt-data! ( )
410 then ( )
411 then ( )
412 else ( )
413 prev-tte-valid? if ( )
414 vpt-data@ vpt-data-fn ( )
415 then ( )
416 prev-tte-invalid ( )
417 then ( )
418 /x +loop ( )
419;
420
421: (vpt-segment) ( va -- )
422 pagesize bounds do ( )
423 i x@ valid-tte? if ( )
424 i vptshift lshift ( va )
425 (vpt-pgmap) ( )
426 then ( )
427 /x +loop ( )
428;
429
430\ walk the vpt and execute acf with va,len,tte on the stack
431\ beginning at the vpt-root, iterate over each tte in that page;
432\ for each valid tte, go to the page it maps and iterate over those tte's;
433\ for each valid tte in those pages, again descend to the mapped page
434\ and iterate over those tte's; these last map the remaining address space
435: vpt-walker ( acf -- )
436 is vpt-data-fn ( )
437 prev-tte-invalid ( )
438 vpt-root pagesize bounds do ( )
439 i x@ valid-tte? if
440 i vptshift lshift ( va )
441 (vpt-segment) ( )
442 then
443 /x +loop
444 prev-tte-valid? if
445 vpt-data@ vpt-data-fn
446 then
447;