X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Farch%2Fx86%2Fmm_phys.c;h=7a28940fd9466a871fcdded12e508bca5bf65d88;hb=86f855a3e417d93976af42dde36f457e89524902;hp=2b2a76491f559a3011725dd015923792e7585b86;hpb=479d0634670b58da044bc58149662adba0ad1d0b;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/arch/x86/mm_phys.c b/KernelLand/Kernel/arch/x86/mm_phys.c index 2b2a7649..7a28940f 100644 --- a/KernelLand/Kernel/arch/x86/mm_phys.c +++ b/KernelLand/Kernel/arch/x86/mm_phys.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include //#define USE_STACK 1 #define TRACE_ALLOCS 0 // Print trace messages on AllocPhys/DerefPhys @@ -14,9 +16,6 @@ static const int addrClasses[] = {0,16,20,24,32,64}; static const int numAddrClasses = sizeof(addrClasses)/sizeof(addrClasses[0]); -// === IMPORTS === -extern void Proc_PrintBacktrace(void); - // === PROTOTYPES === void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges); //tPAddr MM_AllocPhys(void); @@ -41,11 +40,10 @@ void **gaPageNodes = (void*)MM_PAGENODE_BASE; // === CODE === void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) { - Uint i; Uint64 maxAddr = 0; // --- Find largest address - for( i = 0; i < NPMemRanges; i ++ ) + for( Uint i = 0; i < NPMemRanges; i ++ ) { tPMemMapEnt *ent = &PMemRanges[i]; // If entry is RAM and is above `maxAddr`, change `maxAddr` @@ -56,20 +54,33 @@ void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) giTotalMemorySize += ent->Length >> 12; } } + LOG("giTotalMemorySize = %lli KiB", giTotalMemorySize*4); + LOG("maxAddr = 0x%X", maxAddr); + + // Clip to 32-bits + if( maxAddr > (1ULL << 32) ) { + maxAddr = (1ULL << 32); + } giPageCount = maxAddr >> 12; giLastPossibleFree = giPageCount - 1; - memsetd(gaPageBitmap, 0xFFFFFFFF, giPageCount/32); // Set up allocateable space - for( i = 0; i < NPMemRanges; i ++ ) + for( Uint i = 0; i < NPMemRanges; i ++ ) { tPMemMapEnt *ent = &PMemRanges[i]; if( ent->Type == PMEMTYPE_FREE ) { Uint64 startpg = ent->Start / PAGE_SIZE; Uint64 pgcount = ent->Length / PAGE_SIZE; + // Ignore start addresses >32 bits + if( startpg > (1 << 20) ) + continue ; + // Clip lengths to 32-bit address space + if( startpg + pgcount > (1<<20) ) + pgcount = (1<<20) - startpg; + while( startpg % 32 && pgcount ) { gaPageBitmap[startpg/32] &= ~(1U << (startpg%32)); startpg ++; @@ -86,13 +97,14 @@ void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) } else if( ent->Type == PMEMTYPE_USED ) { + // TODO: Clip? giPhysAlloc += ent->Length / PAGE_SIZE; } } // Fill Superpage bitmap // - A set bit means that there are no free pages in this block of 32 - for( i = 0; i < (giPageCount+31)/32; i ++ ) + for( Uint i = 0; i < (giPageCount+31)/32; i ++ ) { if( gaPageBitmap[i] + 1 == 0 ) { gaSuperBitmap[i/32] |= (1 << i%32); @@ -109,29 +121,47 @@ void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) void MM_DumpStatistics(void) { - int i, pg; - for( i = 1; i < numAddrClasses; i ++ ) + for( int i = 1; i < numAddrClasses; i ++ ) { - int first = (i == 1 ? 0 : (1UL << (addrClasses[i-1] - 12))); - int last = (1UL << (addrClasses[i] - 12)) - 1; + const int first = (i == 1 ? 0 : (1UL << (addrClasses[i-1] - 12))); + const int last = MIN( (1UL << (addrClasses[i] - 12)) - 1, giPageCount ); + const int total = last - first + 1; + int nFree = 0; int nMultiRef = 0; int totalRefs = 0; - - if( last > giPageCount ) - last = giPageCount; + bool refpage_valid = !!MM_GetPhysAddr(&gaPageReferences[first]); - int total = last - first + 1; - - for( pg = first; pg < last; pg ++ ) + for( Uint pg = first; pg < last; pg ++ ) { - if( !MM_GetPhysAddr(&gaPageReferences[pg]) || gaPageReferences[pg] == 0 ) { + // Free chunk + if( gaPageBitmap[pg/32] == 0 ) + { + int count = 32 - pg%32; + nFree += count; + pg += count - 1; + continue ; + } + + // Single free + if( !(gaPageBitmap[pg/32] & (1 << pg%32)) ) + { nFree ++; continue ; } - totalRefs += gaPageReferences[pg]; - if(gaPageReferences[pg] > 1) + + // Check if reference page is valid + if( pg % (PAGE_SIZE/sizeof(gaPageReferences[0])) == 0 ) { + refpage_valid = !!MM_GetPhysAddr(&gaPageReferences[pg]); + } + + // + if( refpage_valid && gaPageReferences[pg] > 1 ) { + totalRefs += gaPageReferences[pg]; nMultiRef ++; + } + else + totalRefs ++; } int nUsed = (total - nFree); @@ -139,12 +169,45 @@ void MM_DumpStatistics(void) addrClasses[i], nUsed, total, nMultiRef, nMultiRef ? (totalRefs-(nUsed - nMultiRef)) / nMultiRef : 0 ); + // TODO: Calculate fragentation of physical memory. + // > Somehow support defragmenting? if( last == giPageCount ) break; } Log_Log("MMPhys", "%lli/%lli total pages used, 0 - %i possible free range", giPhysAlloc, giTotalMemorySize, giLastPossibleFree); + + int startpage = 0; + int last_refcnt = 0; + void *last_node = NULL; + for( int pg = 0; pg < giPageCount; pg ++ ) + { + bool output = 0; + int refcount = 0; + void *node = NULL; + if( !(gaPageBitmap[pg/32] & (1 << pg%32)) ) + { + // free + output = 1; + } + else + { + refcount = MM_GetPhysAddr(&gaPageReferences[pg]) ? gaPageReferences[pg] : 1; + node = MM_GetPhysAddr(&gaPageNodes[pg]) ? gaPageNodes[pg] : NULL; + + if( last_refcnt != refcount || last_node != node ) + output = 1; + } + if( output || pg == giPageCount-1 ) + { + if( last_refcnt > 0 ) + Debug("0x%4x+%i: node=%p refcount=%i", pg-startpage, last_node, last_refcnt); + startpage = pg; + } + last_refcnt = refcount; + last_node = node; + } } /** @@ -239,10 +302,8 @@ tPAddr MM_AllocPhys(void) // Release Spinlock Mutex_Release( &glPhysAlloc ); - - LEAVE('X', ret); - if( ret == 0x17FFE000 ) - LogF("TRIP!\n"); + LEAVE('P', ret); + #if TRACE_ALLOCS if( now() > 4000 ) { Log_Debug("PMem", "MM_AllocPhys: RETURN %P (%i free)", ret, giPageCount-giPhysAlloc); @@ -368,6 +429,8 @@ void MM_RefPhys(tPAddr PAddr) // Get page number PAddr >>= 12; + //if( PAddr == 0x15FA000/PAGE_SIZE ) Debug("%p refed %P", __builtin_return_address(0), PAddr*PAGE_SIZE); + // We don't care about non-ram pages if(PAddr >= giPageCount) return; @@ -379,20 +442,36 @@ void MM_RefPhys(tPAddr PAddr) { if( MM_GetPhysAddr( &gaPageReferences[PAddr] ) == 0 ) { - int i, base; - tVAddr addr = ((tVAddr)&gaPageReferences[PAddr]) & ~0xFFF; -// Log_Debug("PMem", "MM_RefPhys: Allocating info for %X", PAddr); + Uint base = PAddr & ~(1024-1); Mutex_Release( &glPhysAlloc ); - if( MM_Allocate( addr ) == 0 ) { + // No infinite recursion, AllocPhys doesn't need the reference array + // TODO: Race condition? (racy on populating) + if( MM_Allocate( &gaPageReferences[base] ) == 0 ) + { Log_KernelPanic("PMem", "MM_RefPhys: Out of physical memory allocating info for %X", PAddr*PAGE_SIZE ); + for(;;); } Mutex_Acquire( &glPhysAlloc ); + // TODO: Solve race condition. (see below) + // [1] See unallocated + // Release lock + // [2] Acquire lock + // See unallocated + // Release lock + // Allocate + // [1] Allocate + // Acquire lock + // Populate + // Release lock + // [2] Acquire lock + // Populate (clobbering) - base = PAddr & ~(1024-1); - for( i = 0; i < 1024; i ++ ) { + // Fill references from allocated bitmap + for( int i = 0; i < 1024; i ++ ) + { gaPageReferences[base + i] = (gaPageBitmap[(base+i)/32] & (1 << (base+i)%32)) ? 1 : 0; } } @@ -423,12 +502,16 @@ void MM_DerefPhys(tPAddr PAddr) // Get page number PAddr >>= 12; + //if( PAddr == 0x196000/PAGE_SIZE ) Debug("%p derefed %P", __builtin_return_address(0), PAddr*PAGE_SIZE); + // We don't care about non-ram pages if(PAddr >= giPageCount) return; // Check if it is freed if( !(gaPageBitmap[PAddr / 32] & (1 << PAddr%32)) ) { - Log_Warning("MMVirt", "MM_DerefPhys - Non-referenced memory dereferenced"); + Log_Warning("MMVirt", "MM_DerefPhys - Non-referenced memory (%P) dereferenced", + PAddr * PAGE_SIZE); + Proc_PrintBacktrace(); return; } @@ -469,7 +552,7 @@ int MM_GetRefCount(tPAddr PAddr) { // Get page number PAddr >>= 12; - + // We don't care about non-ram pages if(PAddr >= giPageCount) return -1; @@ -482,22 +565,19 @@ int MM_GetRefCount(tPAddr PAddr) int MM_SetPageNode(tPAddr PAddr, void *Node) { - tVAddr block_addr; - if( MM_GetRefCount(PAddr) == 0 ) return 1; PAddr /= PAGE_SIZE; - block_addr = (tVAddr) &gaPageNodes[PAddr]; - block_addr &= ~(PAGE_SIZE-1); + void *page_ptr = (void*)( (tVAddr)&gaPageNodes[PAddr] & ~(PAGE_SIZE-1) ); - if( !MM_GetPhysAddr( (void*)block_addr ) ) + if( !MM_GetPhysAddr( page_ptr ) ) { - if( !MM_Allocate( block_addr ) ) { + if( !MM_Allocate( page_ptr ) ) { Log_Warning("PMem", "Unable to allocate Node page"); return -1; } - memset( (void*)block_addr, 0, PAGE_SIZE ); + memset( page_ptr, 0, PAGE_SIZE ); } gaPageNodes[PAddr] = Node;