X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Finclude%2Ftpl_mm_phys_bitmap.h;h=39444d9468a6e6b386405e65e223b89dc96627b6;hb=dd2491a82880ed9b01b5d66b1814d271921797a4;hp=89c942b096b6ca53ce4ca865aa9a45cab5056c10;hpb=7062f86d2f5b71a6b5a3be2a1e9d408ffa196680;p=tpg%2Facess2.git diff --git a/Kernel/include/tpl_mm_phys_bitmap.h b/Kernel/include/tpl_mm_phys_bitmap.h index 89c942b0..39444d94 100644 --- a/Kernel/include/tpl_mm_phys_bitmap.h +++ b/Kernel/include/tpl_mm_phys_bitmap.h @@ -4,8 +4,6 @@ * include/tpl_mm_phys_bitmap.h * Physical Memory Manager Template */ -#define DEBUG 0 - /* * Bitmap Edition * @@ -16,6 +14,10 @@ #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); @@ -33,9 +35,9 @@ Uint32 *gaiPageReferences = (void*)MM_PAGE_REFCOUNTS; // Reference Counts 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 === /** @@ -52,27 +54,47 @@ void MM_Tpl_InitPhys(int MaxRAMPage, void *MemoryMap) 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 ) { @@ -86,6 +108,7 @@ void MM_Tpl_InitPhys(int MaxRAMPage, void *MemoryMap) gbPMM_Init = 1; + LOG("giPhysFirstFree = 0x%x, giPhysLastFree = 0x%x", giPhysFirstFree, giPhysLastFree); LEAVE('-'); } @@ -100,37 +123,21 @@ void MM_Tpl_InitPhys(int MaxRAMPage, void *MemoryMap) 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 @@ -138,17 +145,18 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) { 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 @@ -161,7 +169,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) } nFree ++; addr ++; - LOG("nFree(%i) == %i (0x%x)", nFree, Pages, addr); + LOG("nFree(%i) == %i (1x%x)", nFree, Pages, addr); if(nFree == Pages) break; } @@ -173,11 +181,13 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) 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 @@ -189,27 +199,38 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) 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); @@ -265,6 +286,9 @@ tPAddr MM_AllocPhys(void) 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); } @@ -275,31 +299,41 @@ tPAddr MM_AllocPhys(void) 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 @@ -329,6 +363,8 @@ void MM_DerefPhys(tPAddr PAddr) Uint64 page = PAddr >> 12; if( PAddr >> 12 > giMaxPhysPage ) return ; + + ENTER("PPAddr", PAddr); if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[page] ) ) { @@ -350,13 +386,11 @@ void MM_DerefPhys(tPAddr PAddr) // 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 @@ -365,6 +399,7 @@ void MM_DerefPhys(tPAddr PAddr) gaSuperBitmap[page / (32*32)] |= 1LL << ((page / 32) & 31); } #endif + LEAVE('-'); } int MM_SetPageNode(tPAddr PAddr, void *Node)