// === PROTOTYPES ===
void MM_InitPhys_Multiboot(tMBoot_Info *MBoot);
-tPAddr MM_AllocPhysRange(int Num, int Bits);
-tPAddr MM_AllocPhys(void);
-void MM_RefPhys(tPAddr PAddr);
-void MM_DerefPhys(tPAddr PAddr);
+//tPAddr MM_AllocPhysRange(int Num, int Bits);
+//tPAddr MM_AllocPhys(void);
+//void MM_RefPhys(tPAddr PAddr);
+//void MM_DerefPhys(tPAddr PAddr);
int MM_int_GetRangeID( tPAddr Addr );
// === GLOBALS ===
tMutex glPhysicalPages;
-Uint64 *gaSuperBitmap = (void*)MM_PAGE_SUPBMP; // 1 bit = 64 Pages, 16 MiB Per Word
+Uint64 *gaSuperBitmap = (void*)MM_PAGE_SUPBMP; // 1 bit = 64 Pages, 16 MiB per Word
Uint64 *gaMainBitmap = (void*)MM_PAGE_BITMAP; // 1 bit = 1 Page, 256 KiB per Word
Uint64 *gaMultiBitmap = (void*)MM_PAGE_DBLBMP; // Each bit means that the page is being used multiple times
Uint32 *gaiPageReferences = (void*)MM_PAGE_COUNTS; // Reference Counts
+void **gapPageNodes = (void*)MM_PAGE_NODES; // Reference Counts
tPAddr giFirstFreePage; // First possibly free page
Uint64 giPhysRangeFree[NUM_MM_PHYS_RANGES]; // Number of free pages in each range
Uint64 giPhysRangeFirst[NUM_MM_PHYS_RANGES]; // First free page in each range
if(base & 63) {
Uint64 val = -1LL << (base & 63);
gaSuperBitmap[base / 64] &= ~val;
- size -= (base & 63);
- base += 64 - (base & 63);
+// size -= (base & 63);
+// base += 64 - (base & 63);
}
}
/**
* \brief Allocate a contiguous range of physical pages with a maximum
- * bit size of \a Bits
- * \param Num Number of pages to allocate
- * \param Bits Maximum size of the physical address
- * \note If \a Bits is <= 0, any sized address is used (with preference
+ * bit size of \a MaxBits
+ * \param Pages Number of pages to allocate
+ * \param MaxBits Maximum size of the physical address
+ * \note If \a MaxBits is <= 0, any sized address is used (with preference
* to higher addresses)
*/
-tPAddr MM_AllocPhysRange(int Num, int Bits)
+tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
{
tPAddr addr, ret;
int rangeID;
int nFree = 0, i;
- ENTER("iNum iBits", Num, Bits);
+ ENTER("iPages iBits", Pages, MaxBits);
- if( Bits <= 0 || Bits >= 64 ) // Speedup for the common case
+ if( MaxBits <= 0 || MaxBits >= 64 ) // Speedup for the common case
rangeID = MM_PHYS_MAX;
else
- rangeID = MM_int_GetRangeID( (1LL << Bits) - 1 );
+ rangeID = MM_int_GetRangeID( (1LL << MaxBits) - 1 );
LOG("rangeID = %i", rangeID);
Warning(" MM_AllocPhysRange: Out of free pages");
Log_Warning("Arch",
"Out of memory (unable to fulfil request for %i pages), zero remaining",
- Num
+ Pages
);
LEAVE('i', 0);
return 0;
}
// Check if there is enough in the range
- if(giPhysRangeFree[rangeID] >= Num)
+ if(giPhysRangeFree[rangeID] >= Pages)
{
LOG("{%i,0x%x -> 0x%x}",
giPhysRangeFree[rangeID],
}
nFree ++;
addr ++;
- LOG("nFree(%i) == %i (0x%x)", nFree, Num, addr);
- if(nFree == Num)
+ LOG("nFree(%i) == %i (0x%x)", nFree, Pages, addr);
+ if(nFree == Pages)
break;
}
LOG("nFree = %i", nFree);
// If we don't find a contiguous block, nFree will not be equal
// to Num, so we set it to zero and do the expensive lookup.
- if(nFree != Num) nFree = 0;
+ if(nFree != Pages) nFree = 0;
}
if( !nFree )
{
// Oops. ok, let's do an expensive check (scan down the list
// until a free range is found)
- nFree = 1;
- addr = giPhysRangeLast[ rangeID ];
- // TODO
+// nFree = 1;
+// addr = giPhysRangeLast[ rangeID ];
+ // TODO: Expensive Check
Mutex_Release(&glPhysicalPages);
// TODO: Page out
// ATM. Just Warning
- Warning(" MM_AllocPhysRange: Out of memory (unable to fulfil request for %i pages)", Num);
+ Warning(" MM_AllocPhysRange: Out of memory (unable to fulfil request for %i pages)", Pages);
Log_Warning("Arch",
"Out of memory (unable to fulfil request for %i pages)",
- Num
+ Pages
);
LEAVE('i', 0);
return 0;
LOG("nFree = %i, addr = 0x%08x", nFree, addr);
// Mark pages as allocated
- addr -= Num;
- for( i = 0; i < Num; i++, addr++ )
+ addr -= Pages;
+ for( i = 0; i < Pages; i++, addr++ )
{
gaMainBitmap[addr >> 6] |= 1LL << (addr & 63);
rangeID = MM_int_GetRangeID(addr << 12);
ret = addr; // Save the return address
// Update super bitmap
- Num += addr & (64-1);
+ Pages += addr & (64-1);
addr &= ~(64-1);
- Num = (Num + (64-1)) & ~(64-1);
- for( i = 0; i < Num/64; i++ )
+ Pages = (Pages + (64-1)) & ~(64-1);
+ for( i = 0; i < Pages/64; i++ )
{
if( gaMainBitmap[ addr >> 6 ] + 1 == 0 )
gaSuperBitmap[addr>>12] |= 1LL << ((addr >> 6) & 63);
if( gaiStaticAllocPages[i] ) {
tPAddr ret = gaiStaticAllocPages[i];
gaiStaticAllocPages[i] = 0;
- Log("MM_AllocPhys: Return %x, static alloc %i", ret, i);
+ Log("MM_AllocPhys: Return %P, static alloc %i", ret, i);
return ret;
}
}
{
// Reference again
gaMultiBitmap[ page >> 6 ] |= 1LL << (page&63);
+ if( !MM_GetPhysAddr( ((tVAddr)&gaiPageReferences[ page ]) & ~0xFFF ) ) {
+ if( !MM_Allocate( ((tVAddr)&gaiPageReferences[ page ]) & ~0xFFF ) ) {
+ Log_Error("Arch", "Out of memory when allocating reference count page");
+ return ;
+ }
+ }
gaiPageReferences[ page ] ++;
}
else
}
}
+int MM_GetRefCount( tPAddr PAddr )
+{
+ PAddr >>= 12;
+
+ if( PAddr >> 12 > giMaxPhysPage ) return 0;
+
+ if( gaMultiBitmap[ PAddr >> 6 ] & (1LL << (PAddr&63)) ) {
+ return gaiPageReferences[PAddr];
+ }
+
+ if( gaMainBitmap[ PAddr >> 6 ] & (1LL << (PAddr&63)) )
+ {
+ return 1;
+ }
+ return 0;
+}
+
/**
* \brief Takes a physical address and returns the ID of its range
* \param Addr Physical address of page
else
return MM_PHYS_16BIT;
}
+
+int MM_SetPageNode(tPAddr PAddr, void *Node)
+{
+ tPAddr page = PAddr >> 12;
+ tVAddr node_page = ((tVAddr)&gapPageNodes[page]) & ~(PAGE_SIZE-1);
+
+// if( !MM_GetRefCount(PAddr) ) return 1;
+
+ if( !MM_GetPhysAddr(node_page) ) {
+ if( !MM_Allocate(node_page) )
+ return -1;
+ memset( (void*)node_page, 0, PAGE_SIZE );
+ }
+
+ gapPageNodes[page] = Node;
+ return 0;
+}
+
+int MM_GetPageNode(tPAddr PAddr, void **Node)
+{
+// if( !MM_GetRefCount(PAddr) ) return 1;
+ PAddr >>= 12;
+
+ if( !MM_GetPhysAddr( (tVAddr)&gapPageNodes[PAddr] ) ) {
+ *Node = NULL;
+ return 0;
+ }
+
+ *Node = gapPageNodes[PAddr];
+ return 0;
+}
+