More work on x86_64 port, near compiling now
[tpg/acess2.git] / Kernel / arch / x86_64 / mm_phys.c
index c64e1e0..dd8ddf6 100644 (file)
@@ -4,6 +4,7 @@
  * Physical Memory Manager
  */
 #include <acess.h>
+#include <mboot.h>
 //#include <mm_phys.h>
 
 enum eMMPhys_Ranges
@@ -19,15 +20,42 @@ enum eMMPhys_Ranges
 // === GLOBALS ===
 tSpinlock      glPhysicalPages;
 Uint64 *gaSuperBitmap; // 1 bit = 64 Pages
-Uint64 *gaPrimaryBitmap;       // 1 bit = 1 Page
+Uint64 *gaPrimaryBitmap;       // 1 bit = 64 Pages
+Uint32 *gaiPageReferences;     // 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
 Uint64 giPhysRangeLast[NUM_MM_PHYS_RANGES];    // Last free page in each range
+Uint64 giMaxPhysPage = 0;      // Maximum Physical page
 
 // === CODE ===
-void MM_InitPhys()
+void MM_InitPhys(tMBoot_Info *MBoot)
 {
+       tMBoot_MMapEnt  *mmapStart;
+       tMBoot_MMapEnt  *ent;
+       Uint64  maxAddr = 0;
+       
+       // Scan the physical memory map
+       mmapStart = (void *)( KERNEL_BASE | MBoot->MMapAddr );
+       ent = mmapStart;
+       while( (Uint)ent < (Uint)mmapStart + MBoot->MMapLength )
+       {
+               // Adjust for the size of the entry
+               ent->Size += 4;
+               
+               // 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(maxAddr == 0) {
+               giMaxPhysPage = (MBoot->HighMem >> 2) + 256;    // HighMem is a kByte value
+       }
+       else {
+               giMaxPhysPage = maxAddr >> 12;
+       }
 }
 
 /**
@@ -92,14 +120,14 @@ tPAddr MM_AllocPhysRange(int Num, int Bits)
                                continue;
                        }
                        // Check page block (64 pages)
-                       if( gaPrimaryBitmap[addr >> 6] == -1) {
+                       if( gaSuperBitmap[addr >> (6+6)] & (1 << (addr>>6)&63)) {
                                nFree = 0;
                                addr += 1 << (12+6);
                                addr &= (1 << (12+6)) - 1;
                                continue;
                        }
                        // Check individual page
-                       if( gaPrimaryBitmap[addr >> 6] & (1 << (addr&63)) ) {
+                       if( gaiPageReferences[addr] ) {
                                nFree = 0;
                                addr ++;
                                continue;
@@ -134,6 +162,7 @@ tPAddr MM_AllocPhysRange(int Num, int Bits)
        addr -= Num;
        for( i = 0; i < Num; i++ )
        {
+               gaiPageReferences[addr] = 1;
                gaPrimaryBitmap[addr>>6] |= 1 << (addr & 63);
                if( gaPrimaryBitmap[addr>>6] == -1 )
                        gaSuperBitmap[addr>>12] |= 1 << ((addr >> 6) & 64);
@@ -158,3 +187,30 @@ tPAddr MM_AllocPhys(void)
 {
        return MM_AllocPhysRange(1, -1);
 }
+
+/**
+ * \brief Reference a physical page
+ */
+void MM_RefPhys(tPAddr PAddr)
+{
+       if( PAddr >> 12 > giMaxPhysPage )       return ;
+       gaiPageReferences[ PAddr >> 12 ] ++;
+       
+       gaPrimaryBitmap[PAddr >> 18] |= 1 << ((PAddr>>12) & 63);
+       if( gaPrimaryBitmap[PAddr >> 18] == -1 )
+               gaSuperBitmap[PAddr >> 24] |= 1 << ((PAddr >> 18) & 64);
+}
+
+/**
+ * \brief Dereference a physical page
+ */
+void MM_DerefPhys(tPAddr PAddr)
+{
+       if( PAddr >> 12 > giMaxPhysPage )       return ;
+       gaiPageReferences[ PAddr >> 12 ] --;
+       if( gaiPageReferences[ PAddr >> 12 ] )
+       {
+               gaPrimaryBitmap[PAddr >> 18] &= ~(1 << ((PAddr >> 12) & 63));
+               gaSuperBitmap[PAddr >> 24] &= ~(1 << ((PAddr >> 18) & 64));
+       }
+}

UCC git Repository :: git.ucc.asn.au