* include/tpl_mm_phys_bitmap.h
* Physical Memory Manager Template
*/
-#define DEBUG 0
-
/*
* Bitmap Edition
*
#define MM_PAGE_NODES (MM_PMM_BASE+(MM_MAXPHYSPAGE*sizeof(Uint32)))
#define MM_PAGE_BITMAP (MM_PAGE_NODES+(MM_MAXPHYSPAGE*sizeof(void*)))
+#define PAGE_BITMAP_FREE(__pg) (gaPageBitmaps[(__pg)/32] & (1LL << ((__pg)&31)))
+#define PAGE_BITMAP_SETFREE(__pg) do{gaPageBitmaps[(__pg)/32] |= (1LL << ((__pg)&31));}while(0)
+#define PAGE_BITMAP_SETUSED(__pg) do{gaPageBitmaps[(__pg)/32] &= ~(1LL << ((__pg)&31));}while(0)
+
// === PROTOTYPES ===
//void MM_InitPhys_Multiboot(tMBoot_Info *MBoot);
//tPAddr MM_AllocPhysRange(int Num, int Bits);
Uint32 *gaPageBitmaps = (void*)MM_PAGE_BITMAP; // Used bitmap (1 == avail)
Uint64 giMaxPhysPage = 0; // Maximum Physical page
int gbPMM_Init = 0;
- int gaiPhysRangeFirstFree[MM_NUM_RANGES];
- int gaiPhysRangeLastFree[MM_NUM_RANGES];
- int gaiPhysRangeNumFree[MM_NUM_RANGES];
+ int giPhysFirstFree;
+ int giPhysLastFree;
+ int giPhysNumFree;
// === CODE ===
/**
giMaxPhysPage = MaxRAMPage;
+// for( i = 0; i < MM_RANGE_MAX; i ++ )
+// gaiPhysRangeFirstFree[i] = -1;
+ giPhysFirstFree = -1;
+
while( MM_int_GetMapEntry(MemoryMap, mapIndex++, &rangeStart, &rangeLen) )
{
tVAddr bitmap_page;
+
+ LOG("Range %i, %P to %P", mapIndex-1, rangeStart, rangeLen);
rangeStart /= PAGE_SIZE;
rangeLen /= PAGE_SIZE;
+ giPhysNumFree += rangeLen;
+
+ LOG("rangeStart = 0x%x, rangeLen = 0x%x", rangeStart, rangeLen);
+
+ if( giPhysFirstFree == -1 || giPhysFirstFree > rangeStart )
+ giPhysFirstFree = rangeStart;
+
+ if( giPhysLastFree < rangeStart + rangeLen )
+ giPhysLastFree = rangeStart + rangeLen;
+
+ LOG("giPhysFirstFree = 0x%x, giPhysLastFree = 0x%x", giPhysFirstFree, giPhysLastFree);
+
bitmap_page = (tVAddr)&gaPageBitmaps[rangeStart/32];
bitmap_page &= ~(PAGE_SIZE-1);
// Only need to allocate bitmaps
if( !MM_GetPhysAddr( bitmap_page ) ) {
- if( MM_Allocate( bitmap_page ) ) {
+ if( !MM_Allocate( bitmap_page ) ) {
Log_KernelPanic("PMM", "Out of memory during init, this is bad");
return ;
}
- memset( (void*)bitmap_page, 0, rangeStart/8 & ~(PAGE_SIZE-1) );
+// memset( (void*)bitmap_page, 0, (rangeStart/8) & ~(PAGE_SIZE-1) );
+ memset( (void*)bitmap_page, 0, PAGE_SIZE );
}
// Align to 32 pages
for( ; (rangeStart & 31) && rangeLen > 0; rangeStart++, rangeLen-- ) {
gaPageBitmaps[rangeStart / 32] |= 1 << (rangeStart&31);
+ LOG("gaPageBitmaps[%i] = 0x%x", rangeStart/32, gaPageBitmaps[rangeStart/32]);
}
// Mark blocks of 32 as avail
for( ; rangeLen > 31; rangeStart += 32, rangeLen -= 32 ) {
gbPMM_Init = 1;
+ LOG("giPhysFirstFree = 0x%x, giPhysLastFree = 0x%x", giPhysFirstFree, giPhysLastFree);
LEAVE('-');
}
tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
{
tPAddr addr, ret;
- int rangeID;
int nFree = 0, i;
ENTER("iPages iBits", Pages, MaxBits);
-
- // Get range ID
- if( MaxBits <= 0 || MaxBits >= 64 ) // Speedup for the common case
- rangeID = MM_RANGE_MAX;
- else
- rangeID = MM_int_GetRangeID( (1LL << MaxBits) - 1 );
Mutex_Acquire(&glPhysicalPages);
- // Check if the range actually has any free pages
- while(gaiPhysRangeNumFree[rangeID] == 0 && rangeID)
- rangeID --;
-
- LOG("rangeID = %i", rangeID);
-
// Check if there is enough in the range
- if(gaiPhysRangeNumFree[rangeID] >= Pages)
+ if(giPhysNumFree >= Pages)
{
- LOG("{%i,0x%x -> 0x%x}",
- giPhysRangeFree[rangeID],
- giPhysRangeFirst[rangeID], giPhysRangeLast[rangeID]
- );
+ LOG("{0x%x -> 0x%x}", giPhysFirstFree, giPhysLastFree);
// Do a cheap scan, scanning upwards from the first free page in
// the range
nFree = 0;
- addr = gaiPhysRangeFirstFree[ rangeID ];
- while( addr <= gaiPhysRangeLastFree[ rangeID ] )
+ addr = giPhysFirstFree;
+ while( addr <= giPhysLastFree )
{
#if USE_SUPER_BITMAP
// Check the super bitmap
{
LOG("nFree = %i = 0 (super) (0x%x)", nFree, addr);
nFree = 0;
- addr += 1LL << (6+6);
- addr &= ~0xFFF; // (1LL << 6+6) - 1
+ addr += (32*32);
+ addr &= ~(32*32-1); // (1LL << 6+6) - 1
continue;
}
#endif
+ LOG("gaPageBitmaps[%i] = 0x%x", addr/32, gaPageBitmaps[addr/32]);
// Check page block (32 pages)
if( gaPageBitmaps[addr / 32] == 0) {
- LOG("nFree = %i = 0 (main) (0x%x)", nFree, addr);
+ LOG("nFree = %i = 0 (block) (0x%x)", nFree, addr);
nFree = 0;
- addr += 1LL << (6);
- addr &= ~0x3F;
+ addr += 32;
+ addr &= ~31;
continue;
}
// Check individual page
}
nFree ++;
addr ++;
- LOG("nFree(%i) == %i (0x%x)", nFree, Pages, addr);
+ LOG("nFree(%i) == %i (1x%x)", nFree, Pages, addr);
if(nFree == Pages)
break;
}
if( !nFree )
{
+#if 0
// Oops. ok, let's do an expensive check (scan down the list
// until a free range is found)
nFree = 1;
addr = gaiPhysRangeLastFree[ rangeID ];
// TODO
+#endif
Mutex_Release(&glPhysicalPages);
// TODO: Page out
// ATM. Just Warning
LEAVE('i', 0);
return 0;
}
- LOG("nFree = %i, addr = 0x%08x", nFree, addr);
+ LOG("nFree = %i, addr = 0x%08x", nFree, (addr-Pages) << 12);
// Mark pages as allocated
addr -= Pages;
for( i = 0; i < Pages; i++, addr++ )
{
// Mark as used
- gaPageBitmaps[addr / 32] &= ~(1 << (addr & 31));
+ PAGE_BITMAP_SETUSED(addr);
// Maintain first possible free
- rangeID = MM_int_GetRangeID(addr * PAGE_SIZE);
- gaiPhysRangeNumFree[ rangeID ] --;
- if(addr == gaiPhysRangeFirstFree[ rangeID ])
- gaiPhysRangeFirstFree[ rangeID ] += 1;
+ giPhysNumFree --;
+ if(addr == giPhysFirstFree)
+ giPhysFirstFree += 1;
+ LOG("if( MM_GetPhysAddr( %p ) )", &gaiPageReferences[addr]);
// Mark as referenced if the reference count page is valid
- if(MM_GetPhysAddr( (tVAddr)&gaiPageReferences[addr] )) {
+ if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[addr] ) ) {
gaiPageReferences[addr] = 1;
}
}
- ret = addr; // Save the return address
-
+ ret = addr - Pages; // Save the return address
+ LOG("ret = %x", ret);
+
+ #if TRACE_ALLOCS
+ LogF("MM_AllocPhysRange: %P (%i pages)\n", ret, Pages);
+ if(Pages > 1) {
+ LogF(" also");
+ for(i = 1; i < Pages; i++)
+ LogF(" %P", ret+i);
+ LogF("\n");
+ }
+ #endif
+
#if USE_SUPER_BITMAP
// Update super bitmap
Pages += addr & (32-1);
Log_Error("PMM", "MM_AllocPhys failed duing init");
return 0;
}
+ #if TRACE_ALLOCS
+ Log("AllocPhys by %p", __builtin_return_address(0));
+ #endif
return MM_AllocPhysRange(1, -1);
}
void MM_RefPhys(tPAddr PAddr)
{
tPAddr page = PAddr / PAGE_SIZE;
+ tVAddr refpage = (tVAddr)&gaiPageReferences[page] & ~(PAGE_SIZE-1);
if( page >= giMaxPhysPage ) return ;
-
- if( gaPageBitmaps[ page / 32 ] & (1LL << (page&31)) )
+
+ if( PAGE_BITMAP_FREE(page) )
{
// Allocate
- gaPageBitmaps[page / 32] &= ~(1LL << (page&31));
+ PAGE_BITMAP_SETUSED(page);
#if USE_SUPER_BITMAP
if( gaPageBitmaps[page / 32] == 0 )
gaSuperBitmap[page / (32*32)] &= ~(1LL << ((page / 32) & 31));
#endif
+ if( MM_GetPhysAddr( refpage ) )
+ gaiPageReferences[page] = 1;
}
else
{
- tVAddr refpage = (tVAddr)&gaiPageReferences[page] & ~(PAGE_SIZE-1);
// Reference again
if( !MM_GetPhysAddr( refpage ) )
{
+ int pages_per_page, basepage, i;
if( MM_Allocate(refpage) == 0 ) {
// Out of memory, can this be resolved?
// TODO: Reclaim memory
Log_Error("PMM", "Out of memory (MM_RefPhys)");
return ;
}
- memset((void*)refpage, 0, PAGE_SIZE);
+ pages_per_page = PAGE_SIZE/sizeof(*gaiPageReferences);
+ basepage = page & ~(pages_per_page-1);
+ for( i = 0; i < pages_per_page; i ++ ) {
+ if( PAGE_BITMAP_FREE(basepage+i) )
+ gaiPageReferences[basepage+i] = 0;
+ else
+ gaiPageReferences[basepage+i] = 1;
+ }
gaiPageReferences[page] = 2;
}
else
Uint64 page = PAddr >> 12;
if( PAddr >> 12 > giMaxPhysPage ) return ;
+
+ ENTER("PPAddr", PAddr);
if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[page] ) )
{
// Update the free counts if the page was freed
if( gaPageBitmaps[ page / 32 ] & (1LL << (page&31)) )
{
- int rangeID;
- rangeID = MM_int_GetRangeID( PAddr );
- gaiPhysRangeNumFree[ rangeID ] ++;
- if( gaiPhysRangeFirstFree[rangeID] > page )
- gaiPhysRangeFirstFree[rangeID] = page;
- if( gaiPhysRangeLastFree[rangeID] < page )
- gaiPhysRangeLastFree[rangeID] = page;
+ giPhysNumFree ++;
+ if( giPhysFirstFree == -1 || giPhysFirstFree > page )
+ giPhysFirstFree = page;
+ if( giPhysLastFree < page )
+ giPhysLastFree = page;
}
#if USE_SUPER_BITMAP
gaSuperBitmap[page / (32*32)] |= 1LL << ((page / 32) & 31);
}
#endif
+ LEAVE('-');
}
int MM_SetPageNode(tPAddr PAddr, void *Node)