X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fmm_phys.c;h=07318362da46ea7493ab5440cb9910eaaf9f708a;hb=b68b764267d33a45539b4c910db13fbdae48f193;hp=faef2b3e5c69699ed96bf2a18af0ab4da2416a56;hpb=e5e272c426a28f2f9e69ed2232469575c7409af1;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/mm_phys.c b/Kernel/arch/x86/mm_phys.c index faef2b3e..07318362 100644 --- a/Kernel/arch/x86/mm_phys.c +++ b/Kernel/arch/x86/mm_phys.c @@ -10,16 +10,18 @@ //#define USE_STACK 1 #define TRACE_ALLOCS 0 // Print trace messages on AllocPhys/DerefPhys -#define REFERENCE_BASE 0xE0400000 // === IMPORTS === extern void gKernelEnd; +extern void Proc_PrintBacktrace(void); // === PROTOTYPES === -tPAddr MM_AllocPhys(void); -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; @@ -29,7 +31,9 @@ Uint64 giLastPossibleFree = 0; // Last possible free page (before all pages are Uint32 gaSuperBitmap[1024]; // Blocks of 1024 Pages Uint32 gaPageBitmap[1024*1024/32]; // Individual pages -Uint32 *gaPageReferences; + int *gaPageReferences; +void **gaPageNodes = (void*)MM_PAGENODE_BASE; +#define REFENT_PER_PAGE (0x1000/sizeof(gaPageReferences[0])) // === CODE === void MM_Install(tMBoot_Info *MBoot) @@ -102,26 +106,10 @@ void MM_Install(tMBoot_Info *MBoot) while(num--) MM_RefPhys( (mods[i].Start & ~0xFFF) + (num<<12) ); } - - // Allocate References - //LOG("Reference Pages %i", (giPageCount*4+0xFFF)>>12); - for(num = 0; num < (giPageCount*4+0xFFF)>>12; num++) - { - if( !MM_Allocate( REFERENCE_BASE + (num<<12) ) ) - { - Panic("Oh, ****, no space for the reference pages, that's bad"); - for(;;); - } - } - - //LOG("Filling"); - // Fill references - gaPageReferences = (void*)REFERENCE_BASE; - memsetd(gaPageReferences, 1, kernelPages); - for( num = kernelPages; num < giPageCount; num++ ) - { - gaPageReferences[num] = (gaPageBitmap[ num / 32 ] >> (num&31)) & 1; - } + + gaPageReferences = (void*)MM_REFCOUNT_BASE; + + Log_Log("PMem", "Physical memory set up"); } /** @@ -131,16 +119,60 @@ void MM_Install(tMBoot_Info *MBoot) tPAddr MM_AllocPhys(void) { // int a, b, c; - int indx; + int indx = -1; tPAddr ret; ENTER(""); 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; ) + { + 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; + + // Scan the range + for( indx = first; 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; + } + #elif 0 // Find free page // Scan downwards - #if 1 LOG("giLastPossibleFree = %i", giLastPossibleFree); for( indx = giLastPossibleFree; indx >= 0; ) { @@ -160,6 +192,8 @@ tPAddr MM_AllocPhys(void) } break; } + if( indx >= 0 ) + giLastPossibleFree = indx; LOG("indx = %i", indx); #else c = giLastPossibleFree % 32; @@ -179,6 +213,8 @@ tPAddr MM_AllocPhys(void) for( ; gaPageBitmap[a*32+b] & (1<= 0 ) + giLastPossibleFree = indx; #endif if( indx < 0 ) { @@ -194,27 +230,37 @@ tPAddr MM_AllocPhys(void) Panic("The fuck? Too many pages! (indx = 0x%x)", indx); } + if( indx >= giPageCount ) { + Mutex_Release( &glPhysAlloc ); + Log_Error("PMem", "MM_AllocPhys - indx(%i) > giPageCount(%i)", indx, giPageCount); + LEAVE('i', 0); + return 0; + } + // Mark page used - if(gaPageReferences) - gaPageReferences[ indx ] = 1; + if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[indx] ) ) + 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 Mutex_Release( &glPhysAlloc ); LEAVE('X', ret); #if TRACE_ALLOCS - Log_Debug("PMem", "MM_AllocPhys: RETURN 0x%llx (%i free)", ret, giPageCount-giPhysAlloc); + if( now() > 4000 ) { + Log_Debug("PMem", "MM_AllocPhys: RETURN %P (%i free)", ret, giPageCount-giPhysAlloc); + Proc_PrintBacktrace(); + } #endif return ret; } @@ -328,7 +374,7 @@ tPAddr MM_AllocPhysRange(int Pages, int MaxBits) // Mark pages used for( i = 0; i < Pages; i++ ) { - if(gaPageReferences) + if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[idx*32+sidx] ) ) gaPageReferences[idx*32+sidx] = 1; gaPageBitmap[ idx ] |= 1 << sidx; sidx ++; @@ -360,7 +406,7 @@ void MM_RefPhys(tPAddr PAddr) { // Get page number PAddr >>= 12; - + // We don't care about non-ram pages if(PAddr >= giPageCount) return; @@ -368,8 +414,26 @@ void MM_RefPhys(tPAddr PAddr) Mutex_Acquire( &glPhysAlloc ); // Reference the page - if(gaPageReferences) + if( gaPageReferences ) + { + if( MM_GetPhysAddr( (tVAddr)&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); + } + Mutex_Acquire( &glPhysAlloc ); + + base = PAddr & ~(1024-1); + for( i = 0; i < 1024; i ++ ) { + gaPageReferences[base + i] = (gaPageBitmap[(base+i)/32] & (1 << (base+i)%32)) ? 1 : 0; + } + } gaPageReferences[ PAddr ] ++; + } // Mark as used gaPageBitmap[ PAddr / 32 ] |= 1 << (PAddr&31); @@ -390,13 +454,13 @@ void MM_DerefPhys(tPAddr PAddr) { // Get page number PAddr >>= 12; - + // We don't care about non-ram pages if(PAddr >= giPageCount) return; // Check if it is freed - if(gaPageReferences[ PAddr ] == 0) { - Warning("MM_DerefPhys - Non-referenced memory dereferenced"); + if( !(gaPageBitmap[PAddr / 32] & (1 << PAddr%32)) ) { + Log_Warning("MMVirt", "MM_DerefPhys - Non-referenced memory dereferenced"); return; } @@ -407,21 +471,25 @@ void MM_DerefPhys(tPAddr PAddr) giLastPossibleFree = PAddr; // Dereference - gaPageReferences[ PAddr ] --; - - // Mark as free in bitmaps - if( gaPageReferences[ PAddr ] == 0 ) + if( !MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) || (-- gaPageReferences[PAddr]) == 0 ) { #if TRACE_ALLOCS - Log_Debug("PMem", "MM_DerefPhys: Free'd 0x%x (%i free)", PAddr, giPageCount-giPhysAlloc); + Log_Debug("PMem", "MM_DerefPhys: Free'd %P (%i free)", PAddr<<12, giPageCount-giPhysAlloc); + Proc_PrintBacktrace(); #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) + if(gaPageBitmap[ PAddr / 32 ] == 0) gaSuperBitmap[ PAddr >> 10 ] &= ~(1 << ((PAddr >> 5)&31)); + + if( MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) ) + { + gaPageNodes[PAddr] = NULL; + // TODO: Free Node Page when fully unused + } } - + // Release spinlock Mutex_Release( &glPhysAlloc ); } @@ -429,14 +497,56 @@ void MM_DerefPhys(tPAddr PAddr) /** * \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; + + if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) == 0 ) + return (gaPageBitmap[PAddr / 32] & (1 << PAddr%32)) ? 1 : 0; // Check if it is freed - return gaPageReferences[ Addr ]; + return gaPageReferences[ 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); + + if( !MM_GetPhysAddr( block_addr ) ) + { + if( !MM_Allocate( block_addr ) ) { + Log_Warning("PMem", "Unable to allocate Node page"); + return -1; + } + memset( (void*)block_addr, 0, PAGE_SIZE ); + } + + gaPageNodes[PAddr] = Node; +// Log("gaPageNodes[0x%x] = %p", PAddr, Node); + return 0; } + +int MM_GetPageNode(tPAddr PAddr, void **Node) +{ + if( MM_GetRefCount(PAddr) == 0 ) return 1; + + PAddr /= PAGE_SIZE; + if( !MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) ) { + *Node = NULL; + return 0; + } + *Node = gaPageNodes[PAddr]; + return 0; +} +