X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Farch%2Fx86%2Fmm_phys.c;h=7a28940fd9466a871fcdded12e508bca5bf65d88;hb=HEAD;hp=b0f1c616b7a254a4fbb2e2415ceca99cb5164ca1;hpb=e02f66c7125bf18f77c6c53587238cbd49da2c89;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/arch/x86/mm_phys.c b/KernelLand/Kernel/arch/x86/mm_phys.c index b0f1c616..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); @@ -101,6 +113,7 @@ void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) gaPageReferences = (void*)MM_REFCOUNT_BASE; + Log_Debug("PMem", "maxAddr = %P", maxAddr); Log_Log("PMem", "Physical memory set up (%lli pages of ~%lli MiB used)", giPhysAlloc, (giTotalMemorySize*PAGE_SIZE)/(1024*1024) ); @@ -108,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); @@ -138,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; + } } /** @@ -152,7 +216,6 @@ void MM_DumpStatistics(void) */ tPAddr MM_AllocPhys(void) { - // int a, b, c; int indx = -1; tPAddr ret; @@ -161,7 +224,6 @@ tPAddr MM_AllocPhys(void) Mutex_Acquire( &glPhysAlloc ); // Classful scan - #if 1 { int i; int first, last; @@ -202,52 +264,6 @@ tPAddr MM_AllocPhys(void) // Out of memory? if( i <= 1 ) indx = -1; } - #elif 0 - // Find free page - // Scan downwards - LOG("giLastPossibleFree = %i", giLastPossibleFree); - for( indx = giLastPossibleFree; indx >= 0; ) - { - if( gaSuperBitmap[indx>>10] == -1 ) { - indx -= 1024; - continue; - } - - if( gaPageBitmap[indx>>5] == -1 ) { - indx -= 32; - continue; - } - - if( gaPageBitmap[indx>>5] & (1 << (indx&31)) ) { - indx --; - continue; - } - break; - } - if( indx >= 0 ) - giLastPossibleFree = indx; - LOG("indx = %i", indx); - #else - c = giLastPossibleFree % 32; - b = (giLastPossibleFree / 32) % 32; - a = giLastPossibleFree / 1024; - - LOG("a=%i,b=%i,c=%i", a, b, c); - for( ; gaSuperBitmap[a] == -1 && a >= 0; a-- ); - if(a < 0) { - Mutex_Release( &glPhysAlloc ); - Warning("MM_AllocPhys - OUT OF MEMORY (Called by %p) - %lli/%lli used", - __builtin_return_address(0), giPhysAlloc, giPageCount); - LEAVE('i', 0); - return 0; - } - for( ; gaSuperBitmap[a] & (1<= 0 ) - giLastPossibleFree = indx; - #endif if( indx < 0 ) { Mutex_Release( &glPhysAlloc ); @@ -286,8 +302,8 @@ tPAddr MM_AllocPhys(void) // Release Spinlock Mutex_Release( &glPhysAlloc ); - - LEAVE('X', ret); + LEAVE('P', ret); + #if TRACE_ALLOCS if( now() > 4000 ) { Log_Debug("PMem", "MM_AllocPhys: RETURN %P (%i free)", ret, giPageCount-giPhysAlloc); @@ -330,29 +346,6 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) idx = sidx / 32; sidx %= 32; - #if 0 - LOG("a=%i, b=%i, idx=%i, sidx=%i", a, b, idx, sidx); - - // Find free page - for( ; gaSuperBitmap[a] == -1 && a --; ) b = 31; - if(a < 0) { - Mutex_Release( &glPhysAlloc ); - Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0)); - LEAVE('i', 0); - return 0; - } - LOG("a = %i", a); - for( ; gaSuperBitmap[a] & (1 << b); b-- ) sidx = 31; - LOG("b = %i", b); - idx = a * 32 + b; - for( ; gaPageBitmap[idx] & (1 << sidx); sidx-- ) - LOG("gaPageBitmap[%i] = 0x%08x", idx, gaPageBitmap[idx]); - - LOG("idx = %i, sidx = %i", idx, sidx); - #else - - #endif - // Check if the gap is large enough while( idx >= 0 ) { @@ -436,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; @@ -447,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; } } @@ -491,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; } @@ -537,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; @@ -550,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;