blob: 84a32fcfcdd19d8651e93612bbbf5c46fc32b1ab [file] [log] [blame]
\ ========== Copyright Header Begin ==========================================
\
\ Hypervisor Software File: allocph1.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 ============================================
copyright: Use is subject to license terms.
purpose: Allocator for physical memory - 1-cell version
copyright: Copyright 1990-2003 Sun Microsystems, Inc. All Rights Reserved
\ Methods:
\ claim ( [ phys ] size alignment -- base )
\ If "alignment" is non-zero, allocates at least "size" bytes of
\ physical memory aligned on the indicated boundary, returning
\ its address "base". This implementation rounds
\ "alignment" up to a multiple of the page size.
\
\ If "alignment" is zero, removes the range of physical memory
\ denoted by phys and size from the list of available
\ physical memory, returning "base" equal to "phys"
\
\ release ( phys size -- )
\ Frees the physical memory range denoted by phys and size.
\ clear-mem is a deferred word so that a system-dependent implementation,
\ perhaps using bzero hardware, can be installed in the system-dependent
\ part of the load sequence.
headerless
defer clear-mem ( phys size -- ) ' 2drop is clear-mem
defer initial-memory ( -- adr len ) ' no-memory to initial-memory
headers
root-device
new-device
" memory" device-name
" memory" " device_type" string-property
list: physavail 0 physavail !
headers
: first-phys-avail ( -- phys size )
physavail last-node node-range ( phys size )
;
headerless
: accum-size ( total node -- total' false ) >size @ + false ;
: total-size ( list -- size )
0 swap ['] accum-size find-node 2drop
;
: (claim-phys-callback)
( aln|adr size aln size max min -- aln|adr size false | phys true )
4 " claim-phys" ($callback) if ( adr size )
\ There was no "claim-phys" callback, so we return false to
\ indicate that the firmware should proceed.
false ( adr size false )
else ( adr size [ phys ] err? n )
\ There was a "claim-phys" callback. If it succeeded, we return
\ the result under true to indicate that the operation has
\ been performed. If it failed, we throw the error because we
\ are no longer in charge of allocation services.
drop throw ( aln size phys )
nip nip true
then
;
: alloc-phys-callback? ( aln size -- aln size false | phys true )
2dup -1 0 (claim-phys-callback)
;
: claim-phys-callback? ( adr size -- adr size false | phys true )
2dup pagesize -rot swap dup (claim-phys-callback)
;
: release-phys-callback? ( adr size -- true | adr size false )
2dup 2 " release-phys" ($callback) if ( adr size )
\ There was no "release-phys" callback, so we return false to
\ indicate that the firmware should proceed.
false ( adr size false )
else ( adr size err? n )
\ There was a "release-phys" callback. If it failed, oh well.
\ Discard the arguments and return true to indicate that the
\ operation has been done.
2drop 2drop true
then
;
: allocate-aligned-physical ( alignment size -- phys )
\ Minumum granularity of memory chunks is 1 page
swap pagesize round-up
swap pagesize round-up ( aln+ size+ )
alloc-phys-callback? if exit then ( aln+ size+ )
tuck physavail ( size alignment size list )
allocate-memrange ( size [ adr ] error? )
abort" Insufficient physical memory" ( size adr )
dup rot clear-mem ( phys )
;
variable allow-reclaim true allow-reclaim !
: claim-physical ( adr len -- )
>page-boundaries ( adr' len' )
claim-phys-callback? if drop exit then ( adr' len' )
\ Look first in the monitor's piece list
physavail ['] contained? find-node ( adr len prev next|0 )
is next-node is prev-node ( adr len )
next-node 0= if
allow-reclaim @ 0=
abort" physical address already used" ( adr len )
2drop exit
then
\ There are 4 cases to consider in removing the requested physical
\ 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 - dup if ( adr len node-a,l begin-a,l )
physavail free-memrange
else
2drop
then ( adr len node-a,l )
\ Give back any left-over portion at the end
2swap + -rot + over - ( end-a,l )
?dup if physavail free-memrange else drop then ( )
;
headers
: claim ( [ phys ] size align -- base )
?dup if ( size align )
\ Alignment should be next power of two
swap allocate-aligned-physical ( base )
else ( phys size )
>r dup r> claim-physical ( base )
then ( base )
;
: release ( phys size -- )
>page-boundaries ( adr' size' )
release-phys-callback? if exit then ( adr' size' )
['] 2drop is ?splice ( adr' size' )
physavail free-memrange
;
: close ( -- ) ;
: open ( -- ok? )
physavail @ if true exit then
initial-memory dup if ( phys size )
release
else
2drop
then
true
;
-2 constant mode
finish-device
device-end
headers
stand-init: memory node
" /memory" open-dev memory-node !
;