X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Farch%2Fx86_64%2Fmm_phys.c;h=27c4946e9462fa6969cc498284a4152a872d0ae8;hb=74ea5e7e82ed3a4f7fa981907177cf55b9b88f07;hp=b537a9f4366296f5924e1eef76cfd75c6d1a02b9;hpb=188021d7737255ce5f4f26b9f047b578b4a8969d;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/arch/x86_64/mm_phys.c b/KernelLand/Kernel/arch/x86_64/mm_phys.c index b537a9f4..27c4946e 100644 --- a/KernelLand/Kernel/arch/x86_64/mm_phys.c +++ b/KernelLand/Kernel/arch/x86_64/mm_phys.c @@ -5,7 +5,8 @@ */ #define DEBUG 0 #include -#include +#include +#include #include #define TRACE_REF 0 @@ -25,7 +26,7 @@ extern char gKernelBase[]; extern char gKernelEnd[]; // === PROTOTYPES === -void MM_InitPhys_Multiboot(tMBoot_Info *MBoot); +//void MM_InitPhys(int NPMemRanges, tPMemMapEnt *PMemRanges); //tPAddr MM_AllocPhysRange(int Num, int Bits); //tPAddr MM_AllocPhys(void); //void MM_RefPhys(tPAddr PAddr); @@ -52,6 +53,7 @@ Uint64 giPhysRangeFree[NUM_MM_PHYS_RANGES]; // Number of free pages in each rang 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 +Uint64 giTotalMemorySize = 0; // Only used in init, allows the init code to provide pages for use by // the allocator before the bitmaps exist. // 3 entries because the are three calls to MM_AllocPhys in MM_Map @@ -62,10 +64,8 @@ tPAddr gaiStaticAllocPages[NUM_STATIC_ALLOC] = {0}; /** * \brief Initialise the physical memory map using a Multiboot 1 map */ -void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) +void MM_InitPhys(int NPMemRanges, tPMemMapEnt *PMemRanges) { - tMBoot_MMapEnt *mmapStart; - tMBoot_MMapEnt *ent; Uint64 maxAddr = 0; int numPages, superPages; int i; @@ -73,226 +73,165 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) tVAddr vaddr; tPAddr paddr, firstFreePage; - ENTER("pMBoot=%p", MBoot); + ENTER("iNPMemRanges pPMemRanges", + NPMemRanges, PMemRanges); // Scan the physical memory map // Looking for the top of physical memory - mmapStart = (void *)( KERNEL_BASE | MBoot->MMapAddr ); - LOG("mmapStart = %p", mmapStart); - ent = mmapStart; - while( (Uint)ent < (Uint)mmapStart + MBoot->MMapLength ) + for( i = 0; i < NPMemRanges; i ++ ) { + tPMemMapEnt *ent = &PMemRanges[i]; // Adjust for the size of the entry - ent->Size += 4; - LOG("ent={Type:%i,Base:0x%x,Length:%x", - ent->Type, ent->Base, ent->Length); + LOG("%i: ent={Type:%i,Base:0x%x,Length:%x}", i, ent->Type, ent->Start, ent->Length); // 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(ent->Type == PMEMTYPE_FREE || ent->Type == PMEMTYPE_USED ) + { + if( ent->Start + ent->Length > maxAddr) + maxAddr = ent->Start + ent->Length; + giTotalMemorySize += ent->Length >> 12; + } } - // Did we find a valid end? - if(maxAddr == 0) { - // No, darn, let's just use the HighMem hack - giMaxPhysPage = (MBoot->HighMem >> 2) + 256; // HighMem is a kByte value - } - else { - // Goodie, goodie gumdrops - giMaxPhysPage = maxAddr >> 12; - } + giMaxPhysPage = maxAddr >> 12; LOG("giMaxPhysPage = 0x%x", giMaxPhysPage); - - // Find a contigous section of memory to hold it in - // - Starting from the end of the kernel - // - We also need a region for the super bitmap + + // Get counts of pages needed for basic structures superPages = ((giMaxPhysPage+64*8-1)/(64*8) + 0xFFF) >> 12; - numPages = (giMaxPhysPage + 7) / 8; - numPages = (numPages + 0xFFF) >> 12; + numPages = ((giMaxPhysPage+7)/8 + 0xFFF) >> 12; // bytes to hold bitmap, divided up to nearest page LOG("numPages = %i, superPages = %i", numPages, superPages); - if(maxAddr == 0) + + // --- Allocate Bitmaps --- + int todo = numPages*2 + superPages; + int mapent = NPMemRanges-1; + vaddr = MM_PAGE_BITMAP; + paddr = -1; + while( todo ) { - int todo = numPages*2 + superPages; - // Ok, naieve allocation, just put it after the kernel - // - Allocated Bitmap - vaddr = MM_PAGE_BITMAP; - paddr = (tPAddr)&gKernelEnd - KERNEL_BASE; - while(todo ) + while(PMemRanges[mapent].Type != PMEMTYPE_FREE && mapent != -1) + mapent --; + if( paddr + 1 == 0 ) + paddr = PMemRanges[mapent].Start; + if( mapent == -1 ) { + // OOM During init, bad thing + Log_KernelPanic("PMem", "Out of memory during init"); + for(;;); + } + + // Ensure that the static allocation pool has pages + for( i = 0; i < NUM_STATIC_ALLOC; i++) { - // Allocate statics - for( i = 0; i < NUM_STATIC_ALLOC; i++) { - if(gaiStaticAllocPages[i] != 0) continue; + if(gaiStaticAllocPages[i] == 0) + { gaiStaticAllocPages[i] = paddr; - paddr += 0x1000; + // break to ensure we update the address correctly + break; } - + } + + if( i == NUM_STATIC_ALLOC ) + { + // Map MM_Map(vaddr, paddr); - vaddr += 0x1000; - paddr += 0x1000; - todo --; + // Update virtual pointer + vaddr += 0x1000; if( todo == numPages + superPages ) vaddr = MM_PAGE_DBLBMP; if( todo == superPages ) vaddr = MM_PAGE_SUPBMP; + } + + // Update physical pointer + // (underflows are detected at the top of the loop) + paddr += 0x1000; + if( paddr - PMemRanges[mapent].Start > PMemRanges[mapent].Length ) + mapent --; + else { + // NOTE: This hides some actually valid memory, but since the pmm + // structures have an "infinite" lifetime, this is of no concequence. + PMemRanges[mapent].Start += 0x1000; + PMemRanges[mapent].Length -= 0x1000; } } - // Scan for a nice range - else - { - int todo = numPages*2 + superPages; - paddr = 0; - vaddr = MM_PAGE_BITMAP; - // Scan! - for( - ent = mmapStart; - (Uint)ent < (Uint)mmapStart + MBoot->MMapLength; - ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ) - ) - { - int avail; - - // RAM only please - if( ent->Type != 1 ) - continue; - - // Let's not put it below the kernel, shall we? - if( ent->Base + ent->Size < (tPAddr)&gKernelBase ) - continue; - - LOG("%x <= %x && %x > %x", - ent->Base, (tPAddr)&gKernelBase, - ent->Base + ent->Size, (tPAddr)&gKernelEnd - KERNEL_BASE - ); - // Check if the kernel is in this range - if( ent->Base <= (tPAddr)&gKernelBase - && ent->Base + ent->Length > (tPAddr)&gKernelEnd - KERNEL_BASE ) - { - avail = ent->Length >> 12; - avail -= ((tPAddr)&gKernelEnd - KERNEL_BASE - ent->Base) >> 12; - paddr = (tPAddr)&gKernelEnd - KERNEL_BASE; - } - // No? then we can use all of the block - else - { - avail = ent->Length >> 12; - paddr = ent->Base; - } - - Log("MM_InitPhys_Multiboot: paddr=0x%x, avail=0x%x pg", paddr, avail); - - // Map - while( todo && avail --) - { - // Static Allocations - for( i = 0; i < NUM_STATIC_ALLOC && avail; i++) { - if(gaiStaticAllocPages[i] != 0) continue; - gaiStaticAllocPages[i] = paddr; - paddr += 0x1000; - avail --; - } - if(!avail) break; - - // Map - MM_Map(vaddr, paddr); - todo --; - vaddr += 0x1000; - paddr += 0x1000; - - // Alter the destination address when needed - if(todo == superPages+numPages) - vaddr = MM_PAGE_DBLBMP; - if(todo == superPages) - vaddr = MM_PAGE_SUPBMP; - } - - // Fast quit if there's nothing left to allocate - if( !todo ) break; - } - } + + PMemMap_DumpBlocks(PMemRanges, NPMemRanges); + // Save the current value of paddr to simplify the allocation later firstFreePage = paddr; LOG("Clearing multi bitmap"); - // Fill the bitmaps - memset(gaMultiBitmap, 0, (numPages<<12)/8); - // - initialise to one, then clear the avaliable areas - memset(gaMainBitmap, -1, (numPages<<12)/8); - memset(gaSuperBitmap, -1, (numPages<<12)/(8*64)); - LOG("Setting main bitmap"); + // Fill the bitmaps (set most to "allocated") + memset(gaMultiBitmap, 0, numPages<<12); + memset(gaMainBitmap, 255, numPages<<12); // - Clear all Type=1 areas LOG("Clearing valid regions"); - for( - ent = mmapStart; - (Uint)ent < (Uint)mmapStart + MBoot->MMapLength; - ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ) - ) + for( i = 0; i < NPMemRanges; i ++ ) { + tPMemMapEnt *ent = &PMemRanges[i]; // Check if the type is RAM - if(ent->Type != 1) continue; + if(ent->Type != PMEMTYPE_FREE) continue; // Main bitmap - base = ent->Base >> 12; - size = ent->Size >> 12; - - if(base & 63) { - Uint64 val = -1LL << (base & 63); - gaMainBitmap[base / 64] &= ~val; - size -= (base & 63); - base += 64 - (base & 63); - } - memset( &gaMainBitmap[base / 64], 0, size/8 ); - if( size & 7 ) { - Uint64 val = -1LL << (size & 7); - val <<= (size/8)&7; - gaMainBitmap[base / 64] &= ~val; + base = ent->Start >> 12; + size = ent->Length >> 12; + + LOG("%i: base=%x, size=%x", i, base, size); + if( base % 64 + size < 64 ) + { + Uint64 bits = (1ULL << size) - 1; + bits <<= base % 64; + gaMainBitmap[base / 64] &= ~bits; } - - // Super Bitmap - base = ent->Base >> 12; - size = ent->Size >> 12; - size = (size + (base & 63) + 63) >> 6; - base = base >> 6; - if(base & 63) { - Uint64 val = -1LL << (base & 63); - gaSuperBitmap[base / 64] &= ~val; -// size -= (base & 63); -// base += 64 - (base & 63); + else + { + if(base & 63) + { + // Keep lower bits + Uint64 bits = (1ULL << (base & 63)) - 1; + gaMainBitmap[base / 64] &= bits; + + size -= 64 - base % 64; + base += 64 - base % 64; + } + LOG("%i: base=%x, size=%x", i, base, size); + memset( &gaMainBitmap[base / 64], 0, (size/64)*8 ); + base += size & ~(64-1); + size -= size & ~(64-1); + LOG("%i: base=%x, size=%x", i, base, size); + if( size & 63 ) + { + // Unset lower bits (hence the bitwise not) + Uint64 val = (1ULL << (size & 63)) - 1; + gaMainBitmap[base / 64] &= ~val; + } } } - // Reference the used pages - base = (tPAddr)&gKernelBase >> 12; - size = firstFreePage >> 12; - memset( &gaMainBitmap[base / 64], -1, size/8 ); - if( size & 7 ) { - Uint64 val = -1LL << (size & 7); - val <<= (size/8)&7; - gaMainBitmap[base / 64] |= val; - } - // Free the unused static allocs - for( i = 0; i < NUM_STATIC_ALLOC; i++) { - if(gaiStaticAllocPages[i] != 0) - continue; - gaMainBitmap[ gaiStaticAllocPages[i] >> (12+6) ] - &= ~(1LL << ((gaiStaticAllocPages[i]>>12)&63)); + LOG("Freeing unused static allocations"); + for( i = 0; i < NUM_STATIC_ALLOC; i++) + { + if(gaiStaticAllocPages[i] == 0) + { + gaMainBitmap[ gaiStaticAllocPages[i] >> (12+6) ] + &= ~(1LL << ((gaiStaticAllocPages[i]>>12)&63)); + gaiStaticAllocPages[i] = 0; + } } // Fill the super bitmap LOG("Filling super bitmap"); memset(gaSuperBitmap, 0, superPages<<12); - for( base = 0; base < (size+63)/64; base ++) + int nsuperbits = giMaxPhysPage / 64; // 64 pages per bit + for( i = 0; i < (nsuperbits+63)/64; i ++) { - if( gaMainBitmap[ base ] + 1 == 0 ) - gaSuperBitmap[ base/64 ] |= 1LL << (base&63); + if( gaMainBitmap[ i ] + 1 == 0 ) + gaSuperBitmap[ i/64 ] |= 1ULL << (i % 64); } - // Set free page counts + // Set free page counts for each address class for( base = 1; base < giMaxPhysPage; base ++ ) { int rangeID; @@ -311,8 +250,8 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) // Set last (when the last free page is reached, this won't be // updated anymore, hence will be correct) giPhysRangeLast[ rangeID ] = base; - } - + } + LEAVE('-'); }