X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fmm_phys.c;h=a1feb464dbcdaf578b85dd6805fa8a05398d5520;hb=9d85201216cb35e1b1e051b1d7cdc38eaa5befa4;hp=f091c63ac3a9e4662755b84bbd71bf72a05d07f0;hpb=049de1f2533477716a12a708c097b199eaa8fb6c;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/mm_phys.c b/Kernel/arch/x86/mm_phys.c index f091c63a..a1feb464 100644 --- a/Kernel/arch/x86/mm_phys.c +++ b/Kernel/arch/x86/mm_phys.c @@ -7,7 +7,8 @@ #include #include -#define USE_STACK 1 +//#define USE_STACK 1 +#define TRACE_ALLOCS 0 // Print trace messages on AllocPhys/DerefPhys #define REFERENCE_BASE 0xE0400000 @@ -15,12 +16,15 @@ extern void gKernelEnd; // === PROTOTYPES === -tPAddr MM_AllocPhys(); -tPAddr MM_AllocPhysRange(int Pages, int MaxBits); -void MM_RefPhys(tPAddr PAddr); -void MM_DerefPhys(tPAddr PAddr); +void MM_Install(tMBoot_Info *MBoot); +//tPAddr MM_AllocPhys(void); +//tPAddr MM_AllocPhysRange(int Pages, int MaxBits); +//void MM_RefPhys(tPAddr PAddr); +//void MM_DerefPhys(tPAddr PAddr); +// int MM_GetRefCount(tPAddr PAddr); // === GLOBALS === +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) @@ -39,12 +43,10 @@ void MM_Install(tMBoot_Info *MBoot) tMBoot_MMapEnt *ent; // --- Find largest address - Log("MBoot->MMapAddr = %08x", MBoot->MMapAddr); MBoot->MMapAddr |= KERNEL_BASE; ent = (void *)( MBoot->MMapAddr ); while( (Uint)ent < MBoot->MMapAddr + MBoot->MMapLength ) { - Log(" ent->Size = %08x", ent->Size); // Adjust for size ent->Size += 4; @@ -91,12 +93,10 @@ void MM_Install(tMBoot_Info *MBoot) // Mark Multiboot's pages as taken // - Structure MM_RefPhys( (Uint)MBoot - KERNEL_BASE ); - Log("MBoot->ModuleCount = %i", MBoot->ModuleCount); // - Module List for(i = (MBoot->ModuleCount*sizeof(tMBoot_Module)+0xFFF)>12; i--; ) MM_RefPhys( MBoot->Modules + (i << 12) ); // - Modules - Log("MBoot->Modules = %p", MBoot->Modules); mods = (void*)(MBoot->Modules + KERNEL_BASE); for(i = 0; i < MBoot->ModuleCount; i++) { @@ -109,7 +109,11 @@ void MM_Install(tMBoot_Info *MBoot) //LOG("Reference Pages %i", (giPageCount*4+0xFFF)>>12); for(num = 0; num < (giPageCount*4+0xFFF)>>12; num++) { - MM_Allocate( REFERENCE_BASE + (num<<12) ); + if( !MM_Allocate( REFERENCE_BASE + (num<<12) ) ) + { + Panic("Oh, ****, no space for the reference pages, that's bad"); + for(;;); + } } //LOG("Filling"); @@ -123,22 +127,70 @@ void MM_Install(tMBoot_Info *MBoot) } /** - * \fn tPAddr MM_AllocPhys() + * \fn tPAddr MM_AllocPhys(void) * \brief Allocates a physical page from the general pool */ -tPAddr MM_AllocPhys() +tPAddr MM_AllocPhys(void) { // int a, b, c; - int indx; + int indx = -1; tPAddr ret; ENTER(""); - LOCK( &giPhysAlloc ); + 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; ) + { +// Log("Scanning %i (%i bits)", i, addrClasses[i]); + first = 1 << (addrClasses[i-1] - 12); + last = (1 << (addrClasses[i] - 12)) - 1; + // Range is above the last free page + if( first > giLastPossibleFree ) + continue; + // Last possible free page is in the range + if( last > giLastPossibleFree ) + last = giLastPossibleFree; + +// Log(" first=%i,max=%i", first, last); + // Scan the range + for( indx = first; indx < last; ) + { +// Log("indx = %i (< %i?)", indx, last); + 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 < last ) break; + + giLastPossibleFree = first; // Well, we couldn't find any in this range + } + // Out of memory? + if( i <= 1 ) indx = -1; +// Log("indx = %i", indx); + } + #elif 0 // Find free page // Scan downwards - #if 1 LOG("giLastPossibleFree = %i", giLastPossibleFree); for( indx = giLastPossibleFree; indx >= 0; ) { @@ -146,6 +198,7 @@ tPAddr MM_AllocPhys() indx -= 1024; continue; } + if( gaPageBitmap[indx>>5] == -1 ) { indx -= 32; continue; @@ -157,6 +210,8 @@ tPAddr MM_AllocPhys() } break; } + if( indx >= 0 ) + giLastPossibleFree = indx; LOG("indx = %i", indx); #else c = giLastPossibleFree % 32; @@ -166,8 +221,9 @@ tPAddr MM_AllocPhys() LOG("a=%i,b=%i,c=%i", a, b, c); for( ; gaSuperBitmap[a] == -1 && a >= 0; a-- ); if(a < 0) { - RELEASE( &giPhysAlloc ); - Warning("MM_AllocPhys - OUT OF MEMORY (Called by %p)", __builtin_return_address(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; } @@ -175,27 +231,45 @@ tPAddr MM_AllocPhys() for( ; gaPageBitmap[a*32+b] & (1<= 0 ) + giLastPossibleFree = indx; #endif + if( indx < 0 ) { + Mutex_Release( &glPhysAlloc ); + Warning("MM_AllocPhys - OUT OF MEMORY (Called by %p) - %lli/%lli used (indx = %x)", + __builtin_return_address(0), giPhysAlloc, giPageCount, indx); + Log_Debug("PMem", "giLastPossibleFree = %lli", giLastPossibleFree); + LEAVE('i', 0); + return 0; + } + + if( indx > 0xFFFFF ) { + Panic("The fuck? Too many pages! (indx = 0x%x)", indx); + } + // Mark page used if(gaPageReferences) gaPageReferences[ indx ] = 1; gaPageBitmap[ indx>>5 ] |= 1 << (indx&31); + giPhysAlloc ++; // Get address ret = indx << 12; - giLastPossibleFree = indx; // Mark used block - if(gaPageBitmap[ indx>>5 ] == -1) + if(gaPageBitmap[ indx>>5 ] == -1) { gaSuperBitmap[indx>>10] |= 1 << ((indx>>5)&31); + } // Release Spinlock - RELEASE( &giPhysAlloc ); + Mutex_Release( &glPhysAlloc ); LEAVE('X', ret); - //Log("MM_AllocPhys: RETURN 0x%x", ret); + #if TRACE_ALLOCS + Log_Debug("PMem", "MM_AllocPhys: RETURN 0x%llx (%i free)", ret, giPageCount-giPhysAlloc); + #endif return ret; } @@ -221,7 +295,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) if(MaxBits > PHYS_BITS) MaxBits = PHYS_BITS; // Lock - LOCK( &giPhysAlloc ); + Mutex_Acquire( &glPhysAlloc ); // Set up search state if( giLastPossibleFree > ((tPAddr)1 << (MaxBits-12)) ) { @@ -241,7 +315,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) // Find free page for( ; gaSuperBitmap[a] == -1 && a --; ) b = 31; if(a < 0) { - RELEASE( &giPhysAlloc ); + Mutex_Release( &glPhysAlloc ); Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0)); LEAVE('i', 0); return 0; @@ -299,7 +373,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) // Check if an address was found if( idx < 0 ) { - RELEASE( &giPhysAlloc ); + Mutex_Release( &glPhysAlloc ); Warning("MM_AllocPhysRange - OUT OF MEMORY (Called by %p)", __builtin_return_address(0)); LEAVE('i', 0); return 0; @@ -312,6 +386,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) gaPageReferences[idx*32+sidx] = 1; gaPageBitmap[ idx ] |= 1 << sidx; sidx ++; + giPhysAlloc ++; if(sidx == 32) { sidx = 0; idx ++; } } @@ -322,9 +397,13 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) if(gaPageBitmap[ idx ] == -1) gaSuperBitmap[idx/32] |= 1 << (idx%32); // Release Spinlock - RELEASE( &giPhysAlloc ); + Mutex_Release( &glPhysAlloc ); LEAVE('X', ret); + #if TRACE_ALLOCS + Log_Debug("PMem", "MM_AllocPhysRange: RETURN 0x%llx-0x%llx (%i free)", + ret, ret + (1<= giPageCount) return; // Lock Structures - LOCK( &giPhysAlloc ); + Mutex_Acquire( &glPhysAlloc ); // Reference the page if(gaPageReferences) @@ -354,7 +433,7 @@ void MM_RefPhys(tPAddr PAddr) gaSuperBitmap[PAddr/1024] |= 1 << ((PAddr/32)&31); // Release Spinlock - RELEASE( &giPhysAlloc ); + Mutex_Release( &glPhysAlloc ); } /** @@ -376,7 +455,7 @@ void MM_DerefPhys(tPAddr PAddr) } // Lock Structures - LOCK( &giPhysAlloc ); + Mutex_Acquire( &glPhysAlloc ); if( giLastPossibleFree < PAddr ) giLastPossibleFree = PAddr; @@ -387,27 +466,31 @@ void MM_DerefPhys(tPAddr PAddr) // Mark as free in bitmaps if( gaPageReferences[ PAddr ] == 0 ) { + #if TRACE_ALLOCS + Log_Debug("PMem", "MM_DerefPhys: Free'd 0x%x (%i free)", PAddr, giPageCount-giPhysAlloc); + #endif //LOG("Freed 0x%x by %p\n", PAddr<<12, __builtin_return_address(0)); + giPhysAlloc --; gaPageBitmap[ PAddr / 32 ] &= ~(1 << (PAddr&31)); if(gaPageReferences[ PAddr ] == 0) gaSuperBitmap[ PAddr >> 10 ] &= ~(1 << ((PAddr >> 5)&31)); } // Release spinlock - RELEASE( &giPhysAlloc ); + Mutex_Release( &glPhysAlloc ); } /** * \fn int MM_GetRefCount(tPAddr Addr) */ -int MM_GetRefCount(tPAddr Addr) +int MM_GetRefCount(tPAddr PAddr) { // Get page number - Addr >>= 12; + PAddr >>= 12; // We don't care about non-ram pages - if(Addr >= giPageCount) return -1; + if(PAddr >= giPageCount) return -1; // Check if it is freed - return gaPageReferences[ Addr ]; + return gaPageReferences[ PAddr ]; }