// === IMPORTS ===
-extern void gKernelEnd;
+extern char gKernelEnd[];
+extern void Proc_PrintBacktrace(void);
// === PROTOTYPES ===
void MM_Install(tMBoot_Info *MBoot);
Uint32 gaSuperBitmap[1024]; // Blocks of 1024 Pages
Uint32 gaPageBitmap[1024*1024/32]; // Individual pages
-struct sPageInfo {
- int ReferenceCount;
- void *Node;
- Uint64 Offset;
-} *gaPageInfo;
-#define INFO_PER_PAGE (0x1000/sizeof(gaPageInfo[0]))
+ int *gaPageReferences;
+void **gaPageNodes = (void*)MM_PAGENODE_BASE;
+#define REFENT_PER_PAGE (0x1000/sizeof(gaPageReferences[0]))
// === CODE ===
void MM_Install(tMBoot_Info *MBoot)
MM_RefPhys( (mods[i].Start & ~0xFFF) + (num<<12) );
}
- gaPageInfo = (void*)MM_PAGEINFO_BASE;
+ gaPageReferences = (void*)MM_REFCOUNT_BASE;
Log_Log("PMem", "Physical memory set up");
}
}
// Mark page used
- if( MM_GetPhysAddr( (tVAddr)&gaPageInfo[indx] ) )
- gaPageInfo[ indx ].ReferenceCount = 1;
+ if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[indx] ) )
+ gaPageReferences[indx] = 1;
gaPageBitmap[ indx>>5 ] |= 1 << (indx&31);
giPhysAlloc ++;
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;
}
// Mark pages used
for( i = 0; i < Pages; i++ )
{
- if( MM_GetPhysAddr( (tVAddr)&gaPageInfo[idx*32+sidx] ) )
- gaPageInfo[idx*32+sidx].ReferenceCount = 1;
+ if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[idx*32+sidx] ) )
+ gaPageReferences[idx*32+sidx] = 1;
gaPageBitmap[ idx ] |= 1 << sidx;
sidx ++;
giPhysAlloc ++;
Mutex_Acquire( &glPhysAlloc );
// Reference the page
- if( gaPageInfo )
+ if( gaPageReferences )
{
- if( MM_GetPhysAddr( (tVAddr)&gaPageInfo[PAddr] ) == 0 ) {
- tVAddr addr = ((tVAddr)&gaPageInfo[PAddr]) & ~0xFFF;
- Log_Debug("PMem", "MM_RefPhys: Info not allocated %llx", PAddr);
+ 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");
+ Log_KernelPanic("PMem", "MM_RefPhys: Out of physical memory allocating info for %X", PAddr*PAGE_SIZE);
}
Mutex_Acquire( &glPhysAlloc );
- memset( (void*)addr, 0, 0x1000 );
+
+ base = PAddr & ~(1024-1);
+ for( i = 0; i < 1024; i ++ ) {
+ gaPageReferences[base + i] = (gaPageBitmap[(base+i)/32] & (1 << (base+i)%32)) ? 1 : 0;
+ }
}
- gaPageInfo[ PAddr ].ReferenceCount ++;
+ gaPageReferences[ PAddr ] ++;
}
// Mark as used
giLastPossibleFree = PAddr;
// Dereference
- if( !MM_GetPhysAddr( (tVAddr)&gaPageInfo[PAddr] ) || (-- gaPageInfo[PAddr].ReferenceCount) == 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(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 );
}
// We don't care about non-ram pages
if(PAddr >= giPageCount) return -1;
- if( MM_GetPhysAddr( (tVAddr)&gaPageInfo[PAddr] ) == 0 )
+ if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) == 0 )
return (gaPageBitmap[PAddr / 32] & (1 << PAddr%32)) ? 1 : 0;
// Check if it is freed
- return gaPageInfo[ PAddr ].ReferenceCount;
+ return gaPageReferences[ PAddr ];
}
-/**
- * \brief Sets the node and offset associated with a page
- */
-int MM_SetPageInfo(tPAddr PAddr, void *Node, Uint64 Offset)
+int MM_SetPageNode(tPAddr PAddr, void *Node)
{
- PAddr >>= 12;
+ tVAddr block_addr;
+
+ if( MM_GetRefCount(PAddr) == 0 ) return 1;
+
+ PAddr /= PAGE_SIZE;
- // Page doesn't exist
- if( !(gaPageBitmap[PAddr / 32] & (1 << PAddr%32)) )
- return 1;
- // Allocate info block
- if( MM_GetPhysAddr( (tVAddr)&gaPageInfo[PAddr] ) == 0 )
+ block_addr = (tVAddr) &gaPageNodes[PAddr];
+ block_addr &= ~(PAGE_SIZE-1);
+
+ if( !MM_GetPhysAddr( block_addr ) )
{
- tVAddr addr = ((tVAddr)&gaPageInfo[PAddr]) & ~0xFFF;
- Log_Debug("PMem", "MM_SetPageInfo: Info not allocated %llx", PAddr);
- if( MM_Allocate( addr ) == 0 ) {
- Log_KernelPanic("PMem", "MM_SetPageInfo: Out of physical memory");
+ if( !MM_Allocate( block_addr ) ) {
+ Log_Warning("PMem", "Unable to allocate Node page");
+ return -1;
}
- memset( (void*)addr, 0, 0x1000);
+ memset( (void*)block_addr, 0, PAGE_SIZE );
}
- gaPageInfo[ PAddr ].Node = Node;
- gaPageInfo[ PAddr ].Offset = Offset;
-
+ gaPageNodes[PAddr] = Node;
+// Log("gaPageNodes[0x%x] = %p", PAddr, Node);
return 0;
}
-/**
- * \brief Gets the Node/Offset of a page
- */
-int MM_GetPageInfo(tPAddr PAddr, void **Node, Uint64 *Offset)
+int MM_GetPageNode(tPAddr PAddr, void **Node)
{
- PAddr >>= 12;
-
- // Page doesn't exist
- if( !(gaPageBitmap[PAddr / 32] & (1 << PAddr%32)) )
- return 1;
- // Info is zero if block is not allocated
- if( MM_GetPhysAddr( (tVAddr)&gaPageInfo[PAddr] ) == 0 )
- {
- if(Node) *Node = NULL;
- if(Offset) *Offset = 0;
- }
- else
- {
- if(Node) *Node = gaPageInfo[ PAddr ].Node;
- if(Offset) *Offset = gaPageInfo[ PAddr ].Offset;
+ 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;
}
+