Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / utilities / memlist.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: memlist.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: @(#)memlist.fth 1.9 06/11/01
43purpose:
44copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved
45copyright: Use is subject to license terms.
46
47external
48headers
49
50fload ${BP}/dev/utilities/64bit-ops.fth
51
52\ This struct has to be 64-bit aligned
53\ since some of the components are 64-bit in size.
54struct
55 /n field >next-node
56 /n + \ alignment padding
57 /x field >mem.adr
58 /x field >mem.size
59constant /memnode
60
610 value memlist
620 value prev-node
630 value next-node
64
65\ Some of the functions in this file are called from other places
66\ in pci probe code and are likely to be passed paramerters which
67\ are sign-extended. Hence we need to convert those into unsigned
68\ number until we have a better solution albiet tokenizer fix.
69\ Here are the list of functions,
70\ - free-memrange
71\ - allocate-memrange
72\ - set-node
73\ - round-node-up
74\ - round-node-down
75\ - split-node
76
77\
78\ This routine expects to be called with a valid node, not a pointer to a node
79\
80: (find-node) ( ??? node acf -- ?? prev-node this-node|0 )
81 0 >r >r ( ?? this ) ( r: 0 acf )
82 begin ( ?? this ) ( r: prev acf )
83 r@ over >r ( ?? this acf ) ( r: prev acf this )
84 execute ( ?? acf flag ) ( r: prev acf this )
85 r> swap if ( ?? this ) ( r: prev acf )
86 r> r> ( ?? this acf prev ) ( r: -- )
87 nip swap exit ( ?? prev this|0 ) ( r: -- )
88 else ( ?? this ) ( r: prev acf )
89 r> r> ( ?? this acf prev ) ( r: -- )
90 drop ( ?? this acf ) ( r: -- )
91 swap >r ( ?? acf ) ( r: prev )
92 r@ >next-node @ ( ?? acf this ) ( r: prev )
93 swap >r ( ?? this ) ( r: prev acf )
94 then ( ?? this ) ( r: prev acf )
95 dup 0= until ( ?? this ) ( r: prev acf )
96 r> drop ( ?? this ) ( r: prev )
97 r> swap ( ?? prev this ) ( r: -- )
98;
99
100: find-node ( ?? list acf -- ?? )
101 >r ( ?? list ) ( r: acf )
102 dup to memlist ( ?? ) ( r: acf )
103 @ r> (find-node) ( ?? prev this|0 )
104 to next-node ( ?? prev )
105 to prev-node ( ?? )
106;
107
108: delete-after ( prev-node -- deleted-node )
109 dup >next-node @ tuck ( next prev next )
110 >next-node @ swap ! ( next )
111;
112
113: insert-after ( new-node-adr prev-node-adr -- )
114 >next-node ( new &prev->next )
115 tuck @ ( &prev->next new next )
116 over >next-node ! ( &prev->next new )
117 swap ! ( -- )
118;
119
120
121: set-node ( size adr -- node )
122 unsigned-x swap unsigned-x swap
123 /memnode alloc-mem ( adr size node )
124 dup >next-node off ( adr size node )
125 tuck >mem.adr x! ( node )
126 tuck >mem.size x! ( adr node)
127;
128
129: free-node ( node -- ) /memnode free-mem ;
130
131: node-range ( node -- adr size ) dup >mem.adr x@ swap >mem.size x@ ;
132: prev-start ( -- adr ) prev-node >mem.adr x@ ;
133: node-end ( node -- adr ) node-range + ;
134
135\ Is 'adr' less that the address in the node?
136: lower? ( adr node -- adr flag ) >mem.adr x@ over x>= ;
137
138
139: merged-lower? ( size adr -- [ size adr false ] | true )
140 prev-node if ( size adr )
141 dup prev-node node-end x= if ( size adr )
142 drop prev-node >mem.size +x! ( -- )
143 true exit ( true )
144 then ( size adr )
145 then ( size adr )
146 false ( size adr false )
147;
148
149: merged-upper? ( size adr -- [ size adr false ] | true )
150 next-node if ( size adr )
151 2dup + next-node >mem.adr x@ x= if ( size adr )
152 next-node >mem.adr x! ( size -- )
153 next-node >mem.size +x! ( -- )
154 true exit ( true )
155 then ( size adr )
156 then ( size adr )
157 false ( size adr false )
158;
159
160: free-memrange ( adr size list -- )
161 >r unsigned-x swap unsigned-x r> ( size adr list )
162 dup @ if ( adr size list )
163 ['] lower? find-node ( -- )
164 else ( size adr list )
165 -rot set-node swap ! exit ( -- )
166 then ( -- )
167
168 \ Error check to catch attempts to free already-free memory.
169 next-node if
170 2dup swap bounds swap ( size adr lo hi )
171 next-node >mem.adr x@ -rot xwithin ( size adr flag )
172 if ( size adr flag )
173 ." Freeing memory that is already free: " .x .x cr
174 abort ( -- )
175 then ( -- )
176 then ( size adr )
177
178 merged-lower? if ( -- )
179 \ We attempted to merge the lower node and it worked
180 \ Now we need to check the upper
181 prev-node node-range swap ( size adr )
182 merged-upper? if ( -- )
183 \ We merged upper and lower addresses.
184 next-node >mem.size x@ prev-node >mem.size x!
185 prev-node delete-after ( node )
186 free-node ( -- )
187 else ( size adr )
188 2drop ( -- )
189 then ( -- )
190 exit ( -- )
191 else ( size adr )
192 merged-upper? if ( -- )
193 exit ( -- )
194 then ( -- )
195 then ( size adr )
196
197 set-node ( node )
198 prev-node if ( -- )
199 prev-node insert-after ( -- )
200 else ( node )
201 next-node over >next-node ! ( -- )
202 memlist ! ( -- )
203 then
204;
205
206: round-node-up ( node align memlist -- )
207 swap unsigned-x swap ( node align memlist )
208 to memlist >r ( node )
209 dup >mem.adr x@ dup r> round-up ( node mem mem1 )
210 2dup x<> if ( node mem mem1 )
211 tuck ( node mem1 mem mem1 )
212 over - ( node mem1 mem diff )
213 tuck memlist free-memrange ( node mem1 diff )
214 >r ( node mem1 )
215 over >mem.adr x! ( node )
216 r> negate swap >mem.size +x! ( -- )
217 else ( node mem mem1 )
218 3drop ( -- )
219 then ( -- )
220;
221
222: round-node-down ( node align memlist -- )
223 swap unsigned-x swap ( node align memlist )
224 to memlist >r ( node )
225 dup node-end ( node end )
226 dup r> round-down ( node end end' )
227 2dup x<> if ( node end end' )
228 tuck - ( node end' len )
229 tuck ( node len end' len )
230 memlist free-memrange ( node len )
231 negate swap >mem.size +x! ( -- )
232 else ( node end end' )
233 3drop ( -- )
234 then ( -- )
235;
236
237\
238\ And now the code to carve holes in the list.
239\
240: suitable? ( align size node-adr -- alignment size flag )
241 >r r@ >mem.adr x@ 2 pick round-up ( align size aligned-adr )
242 r> node-range -rot - ( align size node-size waste )
243 2dup x<= if 2drop false exit then ( align size node-size waste )
244 - ( align size aln-node-size )
245 over x>= ( align size flag )
246;
247
248: allocate-memrange ( alignment size list -- phys-adr false | true )
249 rot unsigned-x rot unsigned-x rot ( alignment size list )
250 dup @ if
251 ['] suitable? find-node ( align size )
252 else
253 3drop true exit ( true )
254 then
255
256 next-node 0= if 2drop true exit then ( aln size )
257
258 \ simple check first..
259 \ is this exactly the right size?
260 dup next-node >mem.size x@ x= if ( aln size )
261 \ the size matches..
262 2drop ( -- )
263 prev-node ?dup if ( -- )
264 delete-after ( node )
265 else ( -- )
266 next-node dup >next-node @ memlist ! ( adr node )
267 then ( adr node )
268 dup >mem.adr x@ swap ( adr node )
269 free-node ( adr )
270 false exit ( -- adr false )
271 then
272
273 \ OK we need to snip a node
274 swap ( size aln )
275 over next-node >mem.size x@ swap - >r ( size aln len' )
276 next-node >mem.adr x@ dup >r ( size aln adr )
277 over round-up ( size aln adr' )
278 dup r> x= if ( size aln adr' )
279 \ We can take the space from the front
280 \ of the node, leaving the remainder
281 r> next-node >mem.size x! ( size aln adr' )
282 -rot ( adr size aln )
283 drop next-node >mem.adr +x! ( adr )
284 false ( adr false )
285 exit ( -- adr false )
286 then ( size aln adr' )
287
288 \ OK we've exhausted the easy cases
289 \ Now we get to create a new node to describe the remainder
290 dup next-node >mem.adr x@ - ( size aln adr' diff )
291 dup next-node >mem.size x! ( size aln adr' diff )
292 \ First node is truncated now.
293 rot drop r> swap - ( size adr' diff )
294 -rot dup >r + ( diff adr' )
295 over x0<> if ( diff adr' )
296 set-node next-node insert-after ( -- )
297 else ( diff adr' )
298 2drop ( -- )
299 then ( -- )
300 r> false ( adr false )
301;
302
303
304: biggest? ( largest node -- largest flag )
305 over if ( largest node )
306 over >mem.size x@ ( largest node size1 )
307 over >mem.size x@ x>= if ( largest node )
308 drop ( largest )
309 else ( largest node )
310 nip ( largest' )
311 then ( largest' )
312 else ( largest node )
313 nip ( largest false )
314 then false ( largest flag )
315;
316
317: get-biggest-node ( memlist-ptr -- node )
318 0 swap ( biggest memlist-ptr )
319 dup @ if ( biggest memlist-ptr )
320 ['] biggest? find-node ( biggest )
321 else ( 0 memlist-ptr )
322 drop ( 0 )
323 then ( biggest )
324;
325
326: last-node? ( node -- flag ) >next-node @ 0= ;
327
328: get-last-node ( memlist-ptr -- prev last )
329 dup @ if ( memlist-ptr )
330 ['] last-node? find-node ( -- )
331 prev-node next-node ( prev next )
332 else ( memlist-ptr )
333 drop 0 0 ( 0 0 )
334 then ( prev last )
335;
336
337: found-node? ( want current -- flag ) over = ;
338
339\
340\ This doesn't free the selected node, just cuts it from the list.
341\
342: remove-selected-node ( node memlistptr -- fail? )
343 ['] found-node? find-node drop next-node 0= dup if exit then
344 prev-node ?dup if
345 delete-after drop
346 else
347 next-node >next-node @ memlist !
348 then
349 next-node if 0 next-node >next-node ! then
350;
351
352\ release all the nodes in this list.
353: free-list ( node -- )
354 begin ( node )
355 dup while ( node )
356 dup >next-node @ ( node next )
357 swap free-node ( node )
358 repeat drop ( -- )
359;
360
361\ split node at address
362: split-node ( adr node -- prev next )
363 swap unsigned-x swap ( adr node )
364 2dup node-range over + within if ( adr node )
365 2dup >mem.adr x@ - ( adr node diff )
366 over >mem.size x@ over - ( adr node diff next.len )
367 -rot over >mem.size x! ( adr next.len node )
368 -rot swap set-node ( node next )
369 else
370 nip dup ( node node )
371 then
372;
373