Hash :
1a08f436
Author :
Date :
2010-08-25T09:23:17
change to well-formed svn directory structure. git-svn-id: svn://coreboot.org/openboot/trunk@2 4486e004-3823-0410-90c7-fb508cc143bb
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
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 !
;