Branch
Hash :
1a08f436
Author :
Date :
2010-08-25T09:23:17
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
\ ========== Copyright Header Begin ==========================================
\
\ Hypervisor Software File: allocvir.fth
\
\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
\
\ - Do no alter or remove copyright notices
\
\ - Redistribution and use of this software in source and binary forms, with
\ or without modification, are permitted provided that the following
\ conditions are met:
\
\ - Redistribution of source code must retain the above copyright notice,
\ this list of conditions and the following disclaimer.
\
\ - Redistribution in binary form must reproduce the above copyright notice,
\ this list of conditions and the following disclaimer in the
\ documentation and/or other materials provided with the distribution.
\
\ Neither the name of Sun Microsystems, Inc. or the names of contributors
\ may be used to endorse or promote products derived from this software
\ without specific prior written permission.
\
\ This software is provided "AS IS," without a warranty of any kind.
\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
\
\ You acknowledge that this software is not designed, licensed or
\ intended for use in the design, construction, operation or maintenance of
\ any nuclear facility.
\
\ ========== Copyright Header End ============================================
id: @(#)allocvir.fth 2.38 03/07/17
purpose:
copyright: Copyright 1990-2003 Sun Microsystems, Inc. All Rights Reserved
copyright: Use is subject to license terms.
\ Virtual memory allocator for mapping in devices.
\ allocate-virtual ( size -- phys space adr )
\ Allocates at least "size" bytes of virtual memory. The actual
\ allocation size is "size" rounded up to a multiple of the page size.
\
\ The firmware is allowed to allocate from 2 ranges of virtual memory, by
\ (partially historical) agreement with the OS kernel.
\ The first, and preferred, range is the 2 MByte range from 0xffd0.0000
\ to 0xffef.ffff. This range contains the mappings for the firmware itself,
\ and the firmware's stacks, RAM space, and device mappings, leaving a little
\ more than a megabyte for mapping plug-in devices.
\
\ For larger framebuffers, 1 MByte is not enough, so the firmware is also
\ allowed to allocate from the virtual region below 0xff00.0000. Unix
\ calls this address "Sysbase". There is over 100 MBytes of otherwise
\ unused virtual space between the end of the kernel text+data+bss+buffers
\ at approximately 0xf820.0000 and Sysbase.
\
\ One possible problem with this region below 0xff00.0000 is that it is
\ inaccessable to DVMA from some devices, particularly the AMD Ethernet
\ interface on the 4/60 and derived products. That interface has a 24-bit
\ DMA interface, with bits A31:A24 hardwired to 0xff, so DVMA addresses
\ for that device must be at or above 0xff00.0000.
\
\ One solution is to use the "below 0xff00.0000" region for very large
\ devices, say 1MByte or greater, thus leaving enough space for everything
\ else in the high region above 0xffd0.0000.
\
\ For now, we use a "first-fit" policy and hope.
\ If the PMEG containing "splice-adr" is completely contained within the
\ indicated node, free that PMEG. This code assumes that "splice-adr" itself
\ is contained within the node. If "splice-adr" is a segment boundary,
\ then we don't need to free the PMEG, because it will have already been
\ taken care of at a higher level.
defer check-range ' noop is check-range
root-device
new-device
" virtual-memory" device-name
headers
list: fwvirt \ Virtual memory available list
list: osvirt \ Virtual memory that the OS can use but the firmware can't
headerless
: ?free-segment ( splice-adr node -- )
>r ( splice-adr )
dup segmentsize round-down ( splice-adr seg-adr )
\ Exit if the splice is exactly on a segment boundary
tuck = if drop r> drop exit then ( sdg-adr )
segmentsize ( seg-adr seg-size )
r> contained? if ( seg-adr seg-size )
drop deallocate-segment
else ( seg-adr seg-size )
2drop
then ( )
;
\ Frees the virtual address range "adr len"
: noreclaim-free-virtual ( adr len -- )
>page-boundaries
over monvirtbase dup monvirtsize + within if ( adr len )
fwvirt
else ( adr len )
over low-base dup low-size + within if ( adr len )
fwvirt
else ( adr len )
osvirt
then
then ( adr len memorylist )
free-memrange
;
\ Finds the starting address and size of any segments completely contained
\ within the range adr,len
: enclosed-segments ( adr len -- seg-start seg-len )
bounds >r ( end-adr ) ( r: start-adr )
segmentsize round-down ( seg-end ) ( r: start-adr )
dup r@ u< if ( seg-end ) ( r: start-adr )
drop r> 0 exit ( start-adr 0 ) ( r: start-adr )
then ( seg-end ) ( r: start-adr )
r> segmentsize round-up ( seg-end seg-start )
over umin ( seg-end seg-start' )
tuck - ( seg-start seg-len )
;
: reclaim-segments ( adr len -- )
>page-boundaries
enclosed-segments ( seg-adr seg-len )
bounds ?do ( )
i deallocate-segment ( )
segmentsize +loop ( )
;
headers
\ Frees virtual memory and PMEGs, but not the physical memory behind it
: free-virtual-only ( adr len -- )
>page-boundaries
2dup reclaim-segments
['] ?free-segment is ?splice ( adr' len' )
noreclaim-free-virtual
;
headerless
: segment-boundaries ( adr len -- end-adr seg-end seg-start start-adr )
2dup bounds 2swap ( end-adr start-adr adr len )
enclosed-segments ( end-adr start-adr seg-start seg-len )
bounds rot
;
\ Allocates "segment-level" mapping resources for the indicated address range
: ?allocate-segments ( adr size -- )
segment-boundaries ( end-adr seg-end seg-start start-adr )
?allocate-segment ( end-adr seg-end seg-start )
over swap ?do ( end-adr seg-end )
i ?allocate-segment ( end-adr seg-end )
segmentsize +loop ( end-adr seg-end )
tuck - if ?allocate-segment else drop then ( )
;
\ Allocates at least "size" bytes of virtual memory
headers
: allocate-aligned-virtual ( alignment size -- virt-adr )
\ Minumum granularity of memory chunks is 1 page
swap mmu-pagesize round-up
swap mmu-pagesize round-up ( alignment+ size+ )
tuck fwvirt ( size alignment size list )
allocate-memrange ( size [ adr ] error? )
abort" Insufficient virtual memory" ( size adr )
tuck swap ?allocate-segments ( adr )
;
: allocate-virtual ( size -- virt )
1 swap allocate-aligned-virtual
;
headerless
: claim-virtual ( adr size -- adr )
over >r >page-boundaries ( adr,len' )
\ Look first in the monitor's piece list
fwvirt ['] contained? find-node ( adr,len' prev next|0 )
dup 0= if
\ If not found in the monitor's virtual list, look in
\ the OS's virtual list.
2drop
osvirt ['] contained? find-node ( adr,len' prev next|0 )
then
is next-node is prev-node ( adr,len' )
next-node 0= abort" Virtual address already used" ( adr,len' )
\ There are 4 cases to consider in removing the requested virtual
\ address range from the list:
\ (1) The requested range exactly matches the list node range
\ (2) The requested range is at the beginning of the list node range
\ (3) The requested range is at the end of the list node range
\ (4) The requested range is in the middle of the list node range
\ Remember the range of the node to be deleted
next-node node-range ( adr,len' node-a,l )
\ Remove the node from the list
prev-node delete-after memrange free-node ( adr,len' node-a,l )
\ Give back any left-over portion at the beginning
over 4 pick over - ( adr,len' node-a,l begin-a,l )
dup if noreclaim-free-virtual else 2drop then ( adr,len' node-a,l )
\ Give back any left-over portion at the end
2over + -rot + over - ( adr,len' end-a,l )
dup if noreclaim-free-virtual else 2drop then ( adr,len' )
?allocate-segments ( )
r> ( adr )
;
: add-os-piece ( start-adr end-adr -- )
over - set-node osvirt insert-after
;
headers
[ifdef] notdef
\ The open method of /virtual-memory is highly system dependent.
\ Below is an example open method which may not work for
\ every system. The corret version of this method should
\ be defined in the system dependent MMU driver which presumably
\ knows about the limitations and futures of the MMU hardware.
: open ( -- ok? )
0 memrange ! \ Clear free list
d# 20 memrange more-nodes \ Get enough nodes "forever"
\ Create the available memory list from which the firmware is allowed
\ to dynamically allocate virtual memory.
low-base low-size set-node fwvirt insert-after
monvirtbase monvirtsize set-node fwvirt insert-after
ROMbase dictionary-top over - claim-virtual drop
RAMbase RAMsize claim-virtual drop
\ Create the available memory list from which the firmware is not allowed
\ to dynamically allocate virtual memory.
hole-end hole-start <> if
0 hole-start add-os-piece
hole-end low-base add-os-piece
else
0 low-base add-os-piece
then
low-base low-size + monvirtbase add-os-piece
monvirtbase monvirtsize + 0 add-os-piece
true
;
[then] \ notdef
: close ( -- ) ;
: claim ( [ virt ] size align -- base )
?dup if ( size align )
\ Alignment should be next power of two
swap allocate-aligned-virtual ( base )
else ( virt size )
claim-virtual ( base )
then ( base )
;
: release ( virt size -- ) free-virtual-only ;
: modify ( virt size mode -- )
-rot >page-boundaries bounds ?do ( mode )
dup i pgmap@ mode>tte i pgmap! ( mode )
mmu-pagesize +loop drop ( )
;
: map ( phys-lo phys-hi virt size mode -- )
>r 2dup 2>r map-pages ( ) ( r: mode virt size )
2r> r> modify ( )
;
alias unmap unmap-pages ( virt size -- )
: translate ( virt -- false | phys-lo phys-hi mode true )
dup >physical 2dup -1 -1 d= if ( virt -1 -1 )
3drop false
else ( virt phys-lo phys-hi )
rot pgmap@ tte>mode true ( phys-lo phys-hi mode true )
then
;
pagesize constant pagesize
pagesize " page-size" integer-property
finish-device
device-end
stand-init: Opening the virtual memory package
" /virtual-memory" open-dev mmu-node !
;