3 * - Physical memory manager
10 #define REFERENCE_BASE 0xE0400000
13 extern void gKernelEnd;
16 tPAddr MM_AllocPhys();
17 tPAddr MM_AllocPhysRange(int Pages);
18 void MM_RefPhys(tPAddr Addr);
19 void MM_DerefPhys(tPAddr Addr);
24 Uint32 gaSuperBitmap[1024]; // Blocks of 1024 Pages
25 Uint32 gaPageBitmap[1024*1024/32]; // Individual pages
26 Uint32 *gaPageReferences;
29 void MM_Install(tMBoot_Info *MBoot)
31 Uint kernelPages, num;
36 giPageCount = (MBoot->HighMem >> 2) + 256; // HighMem is a kByte value
37 LOG("giPageCount = %i", giPageCount);
39 // Get used page count
40 kernelPages = (Uint)&gKernelEnd - KERNEL_BASE;
41 kernelPages += 0xFFF; // Page Align
46 memsetd(gaPageBitmap, -1, num);
47 gaPageBitmap[ num ] = (1 << (kernelPages & 31)) - 1;
49 // Fill Superpage bitmap
50 num = kernelPages/(32*32);
51 memsetd(gaSuperBitmap, -1, num);
52 gaSuperBitmap[ num ] = (1 << ((kernelPages / 32) & 31)) - 1;
54 // Mark Multiboot's pages as taken
56 MM_RefPhys( (Uint)MBoot - KERNEL_BASE );
58 for(i = (MBoot->ModuleCount*sizeof(tMBoot_Module)+0xFFF)>12; i--; )
59 MM_RefPhys( MBoot->Modules + (i << 12) );
61 mods = (void*)(MBoot->Modules + KERNEL_BASE);
62 for(i = 0; i < MBoot->ModuleCount; i++)
64 num = (mods[i].End - mods[i].Start + 0xFFF) >> 12;
66 MM_RefPhys( (mods[i].Start & ~0xFFF) + (num<<12) );
69 // Allocate References
70 LOG("Reference Pages %i", (giPageCount*4+0xFFF)>>12);
71 for(num = 0; num < (giPageCount*4+0xFFF)>>12; num++)
73 MM_Allocate( REFERENCE_BASE + (num<<12) );
78 gaPageReferences = (void*)REFERENCE_BASE;
79 memsetd(gaPageReferences, 1, kernelPages);
80 for( num = kernelPages; num < giPageCount; num++ )
82 gaPageReferences[num] = (gaPageBitmap[ num / 32 ] >> (num&31)) & 1;
87 * \fn tPAddr MM_AllocPhys()
88 * \brief Allocates a physical page
92 int num = giPageCount / 32 / 32;
99 for(a=0;gaSuperBitmap[a]==-1&&a<num;a++);
101 RELEASE( &giPhysAlloc );
102 Warning("MM_AllocPhys - OUT OF MEMORY (Called by %p)", __builtin_return_address(0));
105 for(b=0;gaSuperBitmap[a]&(1<<b);b++);
106 for(c=0;gaPageBitmap[a*32+b]&(1<<c);c++);
110 gaPageReferences[a*32*32+b*32+c] = 1;
111 gaPageBitmap[ a*32+b ] |= 1 << c;
114 ret = (a << 22) + (b << 17) + (c << 12);
117 if(gaPageBitmap[ a*32+b ] == -1) gaSuperBitmap[a] |= 1 << b;
120 RELEASE( &giPhysAlloc );
126 * \fn tPAddr MM_AllocPhysRange(int Pages)
127 * \brief Allocate a range of physical pages
128 * \param Pages Number of pages to allocate
130 tPAddr MM_AllocPhysRange(int Pages)
132 int num = giPageCount / 32 / 32;
136 LOCK( &giPhysAlloc );
139 for(a=0;gaSuperBitmap[a]==-1&&a<num;a++);
141 RELEASE( &giPhysAlloc );
142 Warning("MM_AllocPhys - OUT OF MEMORY (Called by %p)", __builtin_return_address(0));
145 for(b=0;gaSuperBitmap[a]&(1<<b);b++);
146 for(c=0;gaPageBitmap[a*32+b]&(1<<c);c++);
150 gaPageReferences[a*32*32+b*32+c] = 1;
151 gaPageBitmap[ a*32+b ] |= 1 << c;
154 ret = (a << 22) + (b << 17) + (c << 12);
157 if(gaPageBitmap[ a*32+b ] == -1) gaSuperBitmap[a] |= 1 << b;
160 RELEASE( &giPhysAlloc );
166 * \fn void MM_RefPhys(tPAddr Addr)
168 void MM_RefPhys(tPAddr Addr)
173 // We don't care about non-ram pages
174 if(Addr >= giPageCount) return;
177 LOCK( &giPhysAlloc );
179 // Reference the page
181 gaPageReferences[ Addr ] ++;
184 gaPageBitmap[ Addr / 32 ] |= 1 << (Addr&31);
187 if(gaPageBitmap[ Addr / 32 ] == -1) gaSuperBitmap[Addr/1024] |= 1 << ((Addr/32)&31);
190 RELEASE( &giPhysAlloc );
194 * \fn void MM_DerefPhys(Uint32 Addr)
196 void MM_DerefPhys(tPAddr Addr)
201 // We don't care about non-ram pages
202 if(Addr >= giPageCount) return;
204 // Check if it is freed
205 if(gaPageReferences[ Addr ] == 0) {
206 Warning("MM_DerefPhys - Non-referenced memory dereferenced");
211 LOCK( &giPhysAlloc );
214 gaPageReferences[ Addr ] --;
216 // Mark as free in bitmaps
217 if( gaPageReferences[ Addr ] == 0 )
219 //LOG("Freed 0x%x by %p\n", Addr<<12, __builtin_return_address(0));
220 gaPageBitmap[ Addr / 32 ] &= ~(1 << (Addr&31));
221 if(gaPageReferences[ Addr ] == 0)
222 gaSuperBitmap[ Addr >> 10 ] &= ~(1 << ((Addr >> 5)&31));
226 RELEASE( &giPhysAlloc );
230 * \fn int MM_GetRefCount(tPAddr Addr)
232 int MM_GetRefCount(tPAddr Addr)
237 // We don't care about non-ram pages
238 if(Addr >= giPageCount) return -1;
240 // Check if it is freed
241 return gaPageReferences[ Addr ];