4 * Physical Memory Manager
11 MM_PHYS_16BIT, // Does anything need this?
12 MM_PHYS_20BIT, // Real-Mode
13 MM_PHYS_24BIT, // ISA DMA
14 MM_PHYS_32BIT, // x86 Hardware
15 MM_PHYS_MAX, // Doesn't care
20 tSpinlock glPhysicalPages;
21 Uint64 *gaSuperBitmap; // 1 bit = 64 Pages
22 Uint64 *gaPrimaryBitmap; // 1 bit = 1 Page
23 tPAddr giFirstFreePage; // First possibly free page
24 Uint64 giPhysRangeFree[NUM_MM_PHYS_RANGES]; // Number of free pages in each range
25 Uint64 giPhysRangeFirst[NUM_MM_PHYS_RANGES]; // First free page in each range
26 Uint64 giPhysRangeLast[NUM_MM_PHYS_RANGES]; // Last free page in each range
34 * \brief Allocate a contiguous range of physical pages with a maximum
36 * \param Num Number of pages to allocate
37 * \param Bits Maximum size of the physical address
38 * \note If \a Bits is <= 0, any sized address is used (with preference
39 * to higher addresses)
41 tPAddr MM_AllocPhysRange(int Num, int Bits)
47 if( Bits <= 0 ) // Speedup for the common case
48 rangeID = MM_PHYS_MAX;
50 rangeID = MM_PHYS_MAX;
52 rangeID = MM_PHYS_32BIT;
54 rangeID = MM_PHYS_24BIT;
56 rangeID = MM_PHYS_20BIT;
58 rangeID = MM_PHYS_16BIT;
60 LOCK(&glPhysicalPages);
62 // Check if the range actually has any free pages
63 while(giPhysRangeFree[rangeID] == 0 && rangeID)
66 // What the? Oh, man. No free pages
67 if(giPhysRangeFree[rangeID] == 0) {
68 RELEASE(&glPhysicalPages);
72 "Out of memory (unable to fulfil request for %i pages), zero remaining",
78 // Check if there is enough in the range
79 if(giPhysRangeFree[rangeID] >= Num)
81 // Do a cheap scan, scanning upwards from the first free page in
84 addr = giPhysRangeFirst[ rangeID ];
85 while( addr < giPhysRangeLast[ rangeID ] )
87 // Check the super bitmap
88 if( gaSuperBitmap[addr >> (6+6)] == -1 ) {
91 addr &= (1 << (6+6)) - 1;
94 // Check page block (64 pages)
95 if( gaPrimaryBitmap[addr >> 6] == -1) {
98 addr &= (1 << (12+6)) - 1;
101 // Check individual page
102 if( gaPrimaryBitmap[addr >> 6] & (1 << (addr&63)) ) {
112 // If we don't find a contiguous block, nFree will not be equal
113 // to Num, so we set it to zero and do the expensive lookup.
114 if(nFree != Num) nFree = 0;
119 // Oops. ok, let's do an expensive check (scan down the list
120 // until a free range is found)
122 addr = giPhysRangeLast[ rangeID ];
123 RELEASE(&glPhysicalPages);
127 "Out of memory (unable to fulfil request for %i pages)",
133 // Mark pages as allocated
135 for( i = 0; i < Num; i++ )
137 gaPrimaryBitmap[addr>>6] |= 1 << (addr & 63);
138 if( gaPrimaryBitmap[addr>>6] == -1 )
139 gaSuperBitmap[addr>>12] |= 1 << ((addr >> 6) & 64);
141 if(addr >> 32) rangeID = MM_PHYS_MAX;
142 else if(addr >> 24) rangeID = MM_PHYS_32BIT;
143 else if(addr >> 20) rangeID = MM_PHYS_24BIT;
144 else if(addr >> 16) rangeID = MM_PHYS_20BIT;
145 else if(addr >> 0) rangeID = MM_PHYS_16BIT;
146 giPhysRangeFree[ rangeID ] --;
149 RELEASE(&glPhysicalPages);
154 * \brief Allocate a single physical page, with no preference as to address
157 tPAddr MM_AllocPhys(void)
159 return MM_AllocPhysRange(1, -1);