Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / os / bootprom / allocph.fth
\ ========== Copyright Header Begin ==========================================
\
\ Hypervisor Software File: allocph.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: @(#)allocph.fth 2.32 06/02/16 19:19:49
purpose:
copyright: Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved
copyright: Copyright 1994 FirmWorks All Rights Reserved
copyright: Use is subject to license terms.
\ Allocator for physical memory.
\ Methods:
\ claim ( [ phys.lo phys.hi ] alignment size -- base.lo base.hi )
\ If "alignment" is non-zero, allocates at least "size" bytes of
\ physical memory aligned on the indicated boundary, returning
\ its address "base.lo base.hi". 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.lo, phys.hi, and size from the list of available
\ physical memory, returning "base.lo base.hi" equal to "phys.lo phys.hi"
\
\ release ( phys.lo phys.hi size -- )
\ Frees the physical memory range denoted by phys.lo, phys.hi, 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.
: no-phys-memory ( -- phys.lo phys.hi len ) 0 0 0 ;
defer clear-mem ( phys space size -- ) ' 3drop is clear-mem
defer initial-memory ( -- phys.lo phys.hi len ) ' no-phys-memory to initial-memory
root-device
new-device
" memory" device-name
list: physavail 0 physavail !
headerless
: bytes>pages ( bytes -- #pages ) pageshift rshift ;
: pages>bytes ( #pages -- bytes ) pageshift lshift ;
: pages>phys-adr,len ( page# #pages -- phys.lo phys.hi size )
pages>bytes >r ( page# ) ( r: size )
dup pages>bytes ( page# p.lo ) ( r: size )
swap bits/cell pageshift - rshift ( p.lo p.hi ) ( r: size )
r> ( phys.lo phys.hi size )
;
: phys-adr,len>pages ( phys.lo phys.hi size -- page# #pages )
bytes>pages >r ( phys.lo phys.hi ) ( r: #pages )
bits/cell pageshift - lshift ( phys.lo page#.hi ) ( r: #pages )
swap bytes>pages or r> ( page# #pages )
;
headers
: first-phys-avail ( -- phys.lo phys.hi size )
physavail last-node ( node )
node-range pages>phys-adr,len ( phys.lo phys.hi size )
;
\ Variable to indicate when all physical memory is clean.
\ Gets turned on after the scrubbing operation is complete.
\ Platforms that know that their memory is pre-cleaned can
\ cause this to be turned on by defining the compile-time
\ switch PreCleanedMemory
also forth definitions variable memory-clean? previous definitions
[ifdef] PreCleanedMemory
memory-clean? on
[else]
memory-clean? off
[then]
headerless
: accum-size ( total node -- total' false ) >size @ + false ;
: total-size ( list -- size-lo size-hi )
0 swap ['] accum-size find-node 2drop
1 pages>phys-adr,len drop
;
: allocate-aligned-physical ( alignment size -- phys-adr space )
\ Minumum granularity of memory chunks is 1 page
swap mmu-pagesize round-up bytes>pages
swap mmu-pagesize round-up bytes>pages ( aln+ size+ )
tuck physavail ( size alignment size list )
allocate-memrange ( size [ adr ] error? )
abort" Insufficient physical memory" ( size adr )
swap pages>phys-adr,len ( phys.lo phys.hi bytes )
\ Don't re-clear memory after it's been scrubbed,
\ or if it's been pre-cleaned.
memory-clean? @ 0= if
3dup clear-mem ( phys.lo phys.hi bytes )
then
drop
;
\ variable allow-reclaim true allow-reclaim !
: claim-physical ( adr space size -- )
['] 2drop is ?splice
swap >r ( adr size ) ( r: space )
>page-boundaries ( adr' size' )
r> swap phys-adr,len>pages ( page# #pages )
\ Look first in the monitor's piece list
physavail ['] contained? find-node ( page#,#pages prev next|0 )
is next-node is prev-node ( page#,#pages )
next-node 0= abort" physical address already used" ( page#,#pages )
\ 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 ( page#,#pages node-a,l )
\ Remove the node from the list
prev-node delete-after memrange free-node ( page#,#pages node-a,l )
\ Give back any left-over portion at the beginning
over 4 pick over - dup if ( page#,#pages node-a,l begin-a,l )
physavail free-memrange
else
2drop
then ( page#,#pages 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 ( )
;
\ Adjust the alignment and size of a given range of memory to match
\ the granularity of what will actually be freed-up.
: range>page-boundaries ( phys.lo phys.hi size -- phys.lo' phys.hi size' )
swap >r ( phys.lo bytes ) ( R: phys.hi )
>page-boundaries ( phys.lo' bytes' ) ( R: phys.hi )
r> swap ( phys.lo' phys.hi bytes' )
;
\ Free-up the given range of physical memory.
\ It's expected to be all adjusted and aligned...
: free-phys-range ( phys.lo' phys.hi size' -- )
phys-adr,len>pages ( page# #pages )
['] 2drop is ?splice
physavail free-memrange ( )
;
\ Initialize the "available" list. Formerly, this was accomplished
\ by using the release function, but now that memory-clearing has
\ been introduced there, this function needs to be distinct.
: init-phys-mem ( phys.lo phys.hi size -- )
range>page-boundaries free-phys-range
;
headers
: claim ( [ phys.lo phys.hi ] size align -- base.lo base.hi )
?dup if ( size align )
\ Alignment should be next power of two
swap allocate-aligned-physical ( base.lo base.hi )
else ( phys.lo phys.hi size )
3dup claim-physical drop ( base.lo base.hi )
then ( base.lo base.hi )
;
: release ( phys.lo phys.hi size -- )
range>page-boundaries ( phys.lo' phys.hi size' )
\ We need to clear the memory when we release it in case we disable
\ clearing at allocation time in the future. Therefore, before we
\ set the 'memory-clean?' variable, we will be clearing the memory
\ during both the 'claim' and 'release' client interface calls.
3dup clear-mem ( phys.lo phys.hi bytes )
free-phys-range ( )
;
: close ( -- ) ;
: open ( -- ok? )
physavail @ if true exit then
initial-memory dup if ( p.lo p.hi size )
init-phys-mem
else
3drop
then
true
;
\ Leave it up to the MMU driver
-1 constant mode
finish-device
device-end
stand-init: Opening the physical memory package
" /memory" open-dev memory-node !
;