X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Farch%2Fx86%2Fmm_phys.c;h=f785ba4537e994c10b212b4047858ef404a2e5de;hb=721192b8e194d068bb6cc59749fe4a36477ddc3f;hp=aa1b26030be7db6e0157071b08d61ca9e842488d;hpb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/arch/x86/mm_phys.c b/KernelLand/Kernel/arch/x86/mm_phys.c index aa1b2603..f785ba45 100644 --- a/KernelLand/Kernel/arch/x86/mm_phys.c +++ b/KernelLand/Kernel/arch/x86/mm_phys.c @@ -4,19 +4,21 @@ */ #define DEBUG 0 #include -#include #include +#include +#include //#define USE_STACK 1 #define TRACE_ALLOCS 0 // Print trace messages on AllocPhys/DerefPhys +static const int addrClasses[] = {0,16,20,24,32,64}; +static const int numAddrClasses = sizeof(addrClasses)/sizeof(addrClasses[0]); // === IMPORTS === -extern char gKernelEnd[]; extern void Proc_PrintBacktrace(void); // === PROTOTYPES === -void MM_Install(tMBoot_Info *MBoot); +void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges); //tPAddr MM_AllocPhys(void); //tPAddr MM_AllocPhysRange(int Pages, int MaxBits); //void MM_RefPhys(tPAddr PAddr); @@ -28,6 +30,7 @@ tMutex glPhysAlloc; Uint64 giPhysAlloc = 0; // Number of allocated pages Uint64 giPageCount = 0; // Total number of pages Uint64 giLastPossibleFree = 0; // Last possible free page (before all pages are used) +Uint64 giTotalMemorySize = 0; // Total number of allocatable pages Uint32 gaSuperBitmap[1024]; // Blocks of 1024 Pages Uint32 gaPageBitmap[1024*1024/32]; // Individual pages @@ -36,80 +39,111 @@ void **gaPageNodes = (void*)MM_PAGENODE_BASE; #define REFENT_PER_PAGE (0x1000/sizeof(gaPageReferences[0])) // === CODE === -void MM_Install(tMBoot_Info *MBoot) +void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) { - Uint kernelPages, num; Uint i; Uint64 maxAddr = 0; - tMBoot_Module *mods; - tMBoot_MMapEnt *ent; // --- Find largest address - MBoot->MMapAddr |= KERNEL_BASE; - ent = (void *)( MBoot->MMapAddr ); - while( (Uint)ent < MBoot->MMapAddr + MBoot->MMapLength ) + for( i = 0; i < NPMemRanges; i ++ ) { - // Adjust for size - ent->Size += 4; - + tPMemMapEnt *ent = &PMemRanges[i]; // If entry is RAM and is above `maxAddr`, change `maxAddr` - if(ent->Type == 1 && ent->Base + ent->Length > maxAddr) - maxAddr = ent->Base + ent->Length; - // Go to next entry - ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ); + if(ent->Type == PMEMTYPE_FREE || ent->Type == PMEMTYPE_USED) + { + if(ent->Start + ent->Length > maxAddr) + maxAddr = ent->Start + ent->Length; + giTotalMemorySize += ent->Length >> 12; + } } - if(maxAddr == 0) { - giPageCount = (MBoot->HighMem >> 2) + 256; // HighMem is a kByte value - } - else { - giPageCount = maxAddr >> 12; - } + giPageCount = maxAddr >> 12; giLastPossibleFree = giPageCount - 1; memsetd(gaPageBitmap, 0xFFFFFFFF, giPageCount/32); // Set up allocateable space - ent = (void *)( MBoot->MMapAddr ); - while( (Uint)ent < MBoot->MMapAddr + MBoot->MMapLength ) - { - memsetd( &gaPageBitmap[ent->Base/(4096*32)], 0, ent->Length/(4096*32) ); - ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ); + for( 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; + while( startpg % 32 && pgcount ) { + gaPageBitmap[startpg/32] &= ~(1U << (startpg%32)); + startpg ++; + pgcount --; + } + memsetd( &gaPageBitmap[startpg/32], 0, pgcount/32 ); + startpg += pgcount - pgcount%32; + pgcount -= pgcount - pgcount%32; + while(pgcount) { + gaPageBitmap[startpg/32] &= ~(1U << (startpg%32)); + startpg ++; + pgcount --; + } + } + else if( ent->Type == PMEMTYPE_USED ) + { + giPhysAlloc += ent->Length / PAGE_SIZE; + } } - - // Get used page count (Kernel) - kernelPages = (Uint)&gKernelEnd - KERNEL_BASE - 0x100000; - kernelPages += 0xFFF; // Page Align - kernelPages >>= 12; - - // Fill page bitmap - num = kernelPages/32; - memsetd( &gaPageBitmap[0x100000/(4096*32)], -1, num ); - gaPageBitmap[ 0x100000/(4096*32) + num ] = (1 << (kernelPages & 31)) - 1; - + // Fill Superpage bitmap - num = kernelPages/(32*32); - memsetd( &gaSuperBitmap[0x100000/(4096*32*32)], -1, num ); - gaSuperBitmap[ 0x100000/(4096*32*32) + num ] = (1 << ((kernelPages / 32) & 31)) - 1; - - // Mark Multiboot's pages as taken - // - Structure - MM_RefPhys( (Uint)MBoot - KERNEL_BASE ); - // - Module List - for(i = (MBoot->ModuleCount*sizeof(tMBoot_Module)+0xFFF)>12; i--; ) - MM_RefPhys( MBoot->Modules + (i << 12) ); - // - Modules - mods = (void*)(MBoot->Modules + KERNEL_BASE); - for(i = 0; i < MBoot->ModuleCount; i++) + // - A set bit means that there are no free pages in this block of 32 + for( i = 0; i < (giPageCount+31)/32; i ++ ) { - num = (mods[i].End - mods[i].Start + 0xFFF) >> 12; - while(num--) - MM_RefPhys( (mods[i].Start & ~0xFFF) + (num<<12) ); + if( gaPageBitmap[i] + 1 == 0 ) { + gaSuperBitmap[i/32] |= (1 << i%32); + } } - + gaPageReferences = (void*)MM_REFCOUNT_BASE; - Log_Log("PMem", "Physical memory set up"); + Log_Log("PMem", "Physical memory set up (%lli pages of ~%lli MiB used)", + giPhysAlloc, (giTotalMemorySize*PAGE_SIZE)/(1024*1024) + ); +} + +void MM_DumpStatistics(void) +{ + int i, pg; + for( i = 1; i < numAddrClasses; i ++ ) + { + int first = (i == 1 ? 0 : (1UL << (addrClasses[i-1] - 12))); + int last = (1UL << (addrClasses[i] - 12)) - 1; + int nFree = 0; + int nMultiRef = 0; + int totalRefs = 0; + + if( last > giPageCount ) + last = giPageCount; + + int total = last - first + 1; + + for( pg = first; pg < last; pg ++ ) + { + if( !MM_GetPhysAddr(&gaPageReferences[pg]) || gaPageReferences[pg] == 0 ) { + nFree ++; + continue ; + } + totalRefs += gaPageReferences[pg]; + if(gaPageReferences[pg] > 1) + nMultiRef ++; + } + + int nUsed = (total - nFree); + Log_Log("MMPhys", "%ipbit - %i/%i used, %i reused, %i average reference count", + addrClasses[i], nUsed, total, nMultiRef, + nMultiRef ? (totalRefs-(nUsed - nMultiRef)) / nMultiRef : 0 + ); + + if( last == giPageCount ) + break; + } + Log_Log("MMPhys", "%lli/%lli total pages used, 0 - %i possible free range", + giPhysAlloc, giTotalMemorySize, giLastPossibleFree); } /** @@ -118,7 +152,6 @@ void MM_Install(tMBoot_Info *MBoot) */ tPAddr MM_AllocPhys(void) { - // int a, b, c; int indx = -1; tPAddr ret; @@ -127,10 +160,7 @@ tPAddr MM_AllocPhys(void) Mutex_Acquire( &glPhysAlloc ); // Classful scan - #if 1 { - const int addrClasses[] = {0,16,20,24,32,64}; - const int numAddrClasses = sizeof(addrClasses)/sizeof(addrClasses[0]); int i; int first, last; for( i = numAddrClasses; i -- > 1; ) @@ -170,52 +200,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 ); @@ -238,7 +222,7 @@ tPAddr MM_AllocPhys(void) } // Mark page used - if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[indx] ) ) + if( MM_GetPhysAddr( &gaPageReferences[indx] ) ) gaPageReferences[indx] = 1; gaPageBitmap[ indx>>5 ] |= 1 << (indx&31); @@ -273,7 +257,6 @@ tPAddr MM_AllocPhys(void) */ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) { - int a, b; int i, idx, sidx; tPAddr ret; @@ -298,31 +281,6 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) } idx = sidx / 32; sidx %= 32; - b = idx % 32; - a = idx / 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 ) @@ -374,7 +332,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) // Mark pages used for( i = 0; i < Pages; i++ ) { - if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[idx*32+sidx] ) ) + if( MM_GetPhysAddr( &gaPageReferences[idx*32+sidx] ) ) gaPageReferences[idx*32+sidx] = 1; gaPageBitmap[ idx ] |= 1 << sidx; sidx ++; @@ -416,14 +374,17 @@ void MM_RefPhys(tPAddr PAddr) // Reference the page if( gaPageReferences ) { - if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) == 0 ) + 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); Mutex_Release( &glPhysAlloc ); if( MM_Allocate( addr ) == 0 ) { - Log_KernelPanic("PMem", "MM_RefPhys: Out of physical memory allocating info for %X", PAddr*PAGE_SIZE); + Log_KernelPanic("PMem", + "MM_RefPhys: Out of physical memory allocating info for %X", + PAddr*PAGE_SIZE + ); } Mutex_Acquire( &glPhysAlloc ); @@ -434,9 +395,13 @@ void MM_RefPhys(tPAddr PAddr) } gaPageReferences[ PAddr ] ++; } - - // Mark as used - gaPageBitmap[ PAddr / 32 ] |= 1 << (PAddr&31); + + // If not already used + if( !(gaPageBitmap[ PAddr / 32 ] & 1 << (PAddr&31)) ) { + giPhysAlloc ++; + // Mark as used + gaPageBitmap[ PAddr / 32 ] |= 1 << (PAddr&31); + } // Mark used block if(gaPageBitmap[ PAddr / 32 ] == -1) @@ -471,7 +436,7 @@ void MM_DerefPhys(tPAddr PAddr) giLastPossibleFree = PAddr; // Dereference - if( !MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) || (-- gaPageReferences[PAddr]) == 0 ) + if( !MM_GetPhysAddr( &gaPageReferences[PAddr] ) || (-- gaPageReferences[PAddr]) == 0 ) { #if TRACE_ALLOCS Log_Debug("PMem", "MM_DerefPhys: Free'd %P (%i free)", PAddr<<12, giPageCount-giPhysAlloc); @@ -483,7 +448,7 @@ void MM_DerefPhys(tPAddr PAddr) if(gaPageBitmap[ PAddr / 32 ] == 0) gaSuperBitmap[ PAddr >> 10 ] &= ~(1 << ((PAddr >> 5)&31)); - if( MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) ) + if( MM_GetPhysAddr( &gaPageNodes[PAddr] ) ) { gaPageNodes[PAddr] = NULL; // TODO: Free Node Page when fully unused @@ -505,7 +470,7 @@ int MM_GetRefCount(tPAddr PAddr) // We don't care about non-ram pages if(PAddr >= giPageCount) return -1; - if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) == 0 ) + if( MM_GetPhysAddr( &gaPageReferences[PAddr] ) == 0 ) return (gaPageBitmap[PAddr / 32] & (1 << PAddr%32)) ? 1 : 0; // Check if it is freed @@ -523,7 +488,7 @@ int MM_SetPageNode(tPAddr PAddr, void *Node) block_addr = (tVAddr) &gaPageNodes[PAddr]; block_addr &= ~(PAGE_SIZE-1); - if( !MM_GetPhysAddr( block_addr ) ) + if( !MM_GetPhysAddr( (void*)block_addr ) ) { if( !MM_Allocate( block_addr ) ) { Log_Warning("PMem", "Unable to allocate Node page"); @@ -542,7 +507,7 @@ int MM_GetPageNode(tPAddr PAddr, void **Node) if( MM_GetRefCount(PAddr) == 0 ) return 1; PAddr /= PAGE_SIZE; - if( !MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) ) { + if( !MM_GetPhysAddr( &gaPageNodes[PAddr] ) ) { *Node = NULL; return 0; }