Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / os / bootprom / allocvir.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: allocvir.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: @(#)allocvir.fth 2.38 03/07/17
43purpose:
44copyright: Copyright 1990-2003 Sun Microsystems, Inc. All Rights Reserved
45copyright: Use is subject to license terms.
46
47\ Virtual memory allocator for mapping in devices.
48
49\ allocate-virtual ( size -- phys space adr )
50\ Allocates at least "size" bytes of virtual memory. The actual
51\ allocation size is "size" rounded up to a multiple of the page size.
52\
53
54\ The firmware is allowed to allocate from 2 ranges of virtual memory, by
55\ (partially historical) agreement with the OS kernel.
56\ The first, and preferred, range is the 2 MByte range from 0xffd0.0000
57\ to 0xffef.ffff. This range contains the mappings for the firmware itself,
58\ and the firmware's stacks, RAM space, and device mappings, leaving a little
59\ more than a megabyte for mapping plug-in devices.
60\
61\ For larger framebuffers, 1 MByte is not enough, so the firmware is also
62\ allowed to allocate from the virtual region below 0xff00.0000. Unix
63\ calls this address "Sysbase". There is over 100 MBytes of otherwise
64\ unused virtual space between the end of the kernel text+data+bss+buffers
65\ at approximately 0xf820.0000 and Sysbase.
66\
67\ One possible problem with this region below 0xff00.0000 is that it is
68\ inaccessable to DVMA from some devices, particularly the AMD Ethernet
69\ interface on the 4/60 and derived products. That interface has a 24-bit
70\ DMA interface, with bits A31:A24 hardwired to 0xff, so DVMA addresses
71\ for that device must be at or above 0xff00.0000.
72\
73\ One solution is to use the "below 0xff00.0000" region for very large
74\ devices, say 1MByte or greater, thus leaving enough space for everything
75\ else in the high region above 0xffd0.0000.
76\
77\ For now, we use a "first-fit" policy and hope.
78
79\ If the PMEG containing "splice-adr" is completely contained within the
80\ indicated node, free that PMEG. This code assumes that "splice-adr" itself
81\ is contained within the node. If "splice-adr" is a segment boundary,
82\ then we don't need to free the PMEG, because it will have already been
83\ taken care of at a higher level.
84
85defer check-range ' noop is check-range
86
87root-device
88new-device
89
90" virtual-memory" device-name
91
92headers
93list: fwvirt \ Virtual memory available list
94list: osvirt \ Virtual memory that the OS can use but the firmware can't
95
96headerless
97
98: ?free-segment ( splice-adr node -- )
99 >r ( splice-adr )
100 dup segmentsize round-down ( splice-adr seg-adr )
101 \ Exit if the splice is exactly on a segment boundary
102 tuck = if drop r> drop exit then ( sdg-adr )
103 segmentsize ( seg-adr seg-size )
104 r> contained? if ( seg-adr seg-size )
105 drop deallocate-segment
106 else ( seg-adr seg-size )
107 2drop
108 then ( )
109;
110
111\ Frees the virtual address range "adr len"
112
113: noreclaim-free-virtual ( adr len -- )
114 >page-boundaries
115 over monvirtbase dup monvirtsize + within if ( adr len )
116 fwvirt
117 else ( adr len )
118 over low-base dup low-size + within if ( adr len )
119 fwvirt
120 else ( adr len )
121 osvirt
122 then
123 then ( adr len memorylist )
124 free-memrange
125;
126\ Finds the starting address and size of any segments completely contained
127\ within the range adr,len
128
129: enclosed-segments ( adr len -- seg-start seg-len )
130 bounds >r ( end-adr ) ( r: start-adr )
131 segmentsize round-down ( seg-end ) ( r: start-adr )
132 dup r@ u< if ( seg-end ) ( r: start-adr )
133 drop r> 0 exit ( start-adr 0 ) ( r: start-adr )
134 then ( seg-end ) ( r: start-adr )
135 r> segmentsize round-up ( seg-end seg-start )
136 over umin ( seg-end seg-start' )
137 tuck - ( seg-start seg-len )
138;
139
140
141: reclaim-segments ( adr len -- )
142 >page-boundaries
143 enclosed-segments ( seg-adr seg-len )
144 bounds ?do ( )
145 i deallocate-segment ( )
146 segmentsize +loop ( )
147;
148
149headers
150\ Frees virtual memory and PMEGs, but not the physical memory behind it
151: free-virtual-only ( adr len -- )
152 >page-boundaries
153 2dup reclaim-segments
154 ['] ?free-segment is ?splice ( adr' len' )
155 noreclaim-free-virtual
156;
157
158headerless
159: segment-boundaries ( adr len -- end-adr seg-end seg-start start-adr )
160 2dup bounds 2swap ( end-adr start-adr adr len )
161 enclosed-segments ( end-adr start-adr seg-start seg-len )
162 bounds rot
163;
164
165\ Allocates "segment-level" mapping resources for the indicated address range
166
167: ?allocate-segments ( adr size -- )
168 segment-boundaries ( end-adr seg-end seg-start start-adr )
169 ?allocate-segment ( end-adr seg-end seg-start )
170 over swap ?do ( end-adr seg-end )
171 i ?allocate-segment ( end-adr seg-end )
172 segmentsize +loop ( end-adr seg-end )
173 tuck - if ?allocate-segment else drop then ( )
174;
175
176\ Allocates at least "size" bytes of virtual memory
177headers
178: allocate-aligned-virtual ( alignment size -- virt-adr )
179 \ Minumum granularity of memory chunks is 1 page
180 swap mmu-pagesize round-up
181 swap mmu-pagesize round-up ( alignment+ size+ )
182 tuck fwvirt ( size alignment size list )
183 allocate-memrange ( size [ adr ] error? )
184 abort" Insufficient virtual memory" ( size adr )
185 tuck swap ?allocate-segments ( adr )
186;
187
188: allocate-virtual ( size -- virt )
189 1 swap allocate-aligned-virtual
190;
191headerless
192: claim-virtual ( adr size -- adr )
193 over >r >page-boundaries ( adr,len' )
194 \ Look first in the monitor's piece list
195 fwvirt ['] contained? find-node ( adr,len' prev next|0 )
196 dup 0= if
197 \ If not found in the monitor's virtual list, look in
198 \ the OS's virtual list.
199 2drop
200 osvirt ['] contained? find-node ( adr,len' prev next|0 )
201 then
202 is next-node is prev-node ( adr,len' )
203
204 next-node 0= abort" Virtual address already used" ( adr,len' )
205
206 \ There are 4 cases to consider in removing the requested virtual
207 \ address range from the list:
208 \ (1) The requested range exactly matches the list node range
209 \ (2) The requested range is at the beginning of the list node range
210 \ (3) The requested range is at the end of the list node range
211 \ (4) The requested range is in the middle of the list node range
212
213 \ Remember the range of the node to be deleted
214 next-node node-range ( adr,len' node-a,l )
215
216 \ Remove the node from the list
217 prev-node delete-after memrange free-node ( adr,len' node-a,l )
218
219 \ Give back any left-over portion at the beginning
220 over 4 pick over - ( adr,len' node-a,l begin-a,l )
221 dup if noreclaim-free-virtual else 2drop then ( adr,len' node-a,l )
222
223 \ Give back any left-over portion at the end
224 2over + -rot + over - ( adr,len' end-a,l )
225 dup if noreclaim-free-virtual else 2drop then ( adr,len' )
226
227 ?allocate-segments ( )
228 r> ( adr )
229;
230
231: add-os-piece ( start-adr end-adr -- )
232 over - set-node osvirt insert-after
233;
234
235headers
236[ifdef] notdef
237\ The open method of /virtual-memory is highly system dependent.
238\ Below is an example open method which may not work for
239\ every system. The corret version of this method should
240\ be defined in the system dependent MMU driver which presumably
241\ knows about the limitations and futures of the MMU hardware.
242: open ( -- ok? )
243 0 memrange ! \ Clear free list
244 d# 20 memrange more-nodes \ Get enough nodes "forever"
245
246 \ Create the available memory list from which the firmware is allowed
247 \ to dynamically allocate virtual memory.
248
249 low-base low-size set-node fwvirt insert-after
250 monvirtbase monvirtsize set-node fwvirt insert-after
251
252 ROMbase dictionary-top over - claim-virtual drop
253 RAMbase RAMsize claim-virtual drop
254
255 \ Create the available memory list from which the firmware is not allowed
256 \ to dynamically allocate virtual memory.
257
258 hole-end hole-start <> if
259 0 hole-start add-os-piece
260 hole-end low-base add-os-piece
261 else
262 0 low-base add-os-piece
263 then
264 low-base low-size + monvirtbase add-os-piece
265 monvirtbase monvirtsize + 0 add-os-piece
266
267 true
268;
269[then] \ notdef
270
271: close ( -- ) ;
272
273: claim ( [ virt ] size align -- base )
274 ?dup if ( size align )
275 \ Alignment should be next power of two
276 swap allocate-aligned-virtual ( base )
277 else ( virt size )
278 claim-virtual ( base )
279 then ( base )
280;
281: release ( virt size -- ) free-virtual-only ;
282
283: modify ( virt size mode -- )
284 -rot >page-boundaries bounds ?do ( mode )
285 dup i pgmap@ mode>tte i pgmap! ( mode )
286 mmu-pagesize +loop drop ( )
287;
288
289: map ( phys-lo phys-hi virt size mode -- )
290 >r 2dup 2>r map-pages ( ) ( r: mode virt size )
291 2r> r> modify ( )
292;
293
294alias unmap unmap-pages ( virt size -- )
295
296: translate ( virt -- false | phys-lo phys-hi mode true )
297 dup >physical 2dup -1 -1 d= if ( virt -1 -1 )
298 3drop false
299 else ( virt phys-lo phys-hi )
300 rot pgmap@ tte>mode true ( phys-lo phys-hi mode true )
301 then
302;
303pagesize constant pagesize
304pagesize " page-size" integer-property
305
306finish-device
307device-end
308
309stand-init: Opening the virtual memory package
310 " /virtual-memory" open-dev mmu-node !
311;