X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86_64%2Fmm_phys.c;h=dd8ddf660f0176fec163b765874699b4d48db0f8;hb=9f407c493c33928e0f19b834699d9694036ca42e;hp=c64e1e03acea7dd0139a17039caac2d94324a7d4;hpb=33bcf4b3feb0e5e4548548bf3d2a50c52ffb6115;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86_64/mm_phys.c b/Kernel/arch/x86_64/mm_phys.c index c64e1e03..dd8ddf66 100644 --- a/Kernel/arch/x86_64/mm_phys.c +++ b/Kernel/arch/x86_64/mm_phys.c @@ -4,6 +4,7 @@ * Physical Memory Manager */ #include +#include //#include 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)); + } +}