From 95a530ccd8a001ca1488d7265268cf8bee2b650e Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 29 May 2010 08:02:31 +0800 Subject: [PATCH 1/1] Nearly completed physical init --- Kernel/Makefile.BuildNum | 2 +- Kernel/arch/x86_64/include/mm_virt.h | 9 +- Kernel/arch/x86_64/mm_phys.c | 170 ++++++++++++++++++--------- 3 files changed, 120 insertions(+), 61 deletions(-) diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index 4e90b47c..8f11b0e3 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 2263 +BUILD_NUM = 2264 diff --git a/Kernel/arch/x86_64/include/mm_virt.h b/Kernel/arch/x86_64/include/mm_virt.h index 26753362..baade6ea 100644 --- a/Kernel/arch/x86_64/include/mm_virt.h +++ b/Kernel/arch/x86_64/include/mm_virt.h @@ -29,7 +29,9 @@ * D000 00000000 - D080 00000000 39 512 GiB Per-Process Data * D080 00000000 - D100 00000000 39 512 GiB Kernel Supplied User Code * E000 00000000 - E400 00000000 42 4 TiB Physical Page Reference Counts (2**40 = 2**52 bytes) - * E400 00000000 - E400 80000000 31 2 GiB Physical Page Super Bitmap (64 pages per bit) + * E400 00000000 - E480 00000000 39 512 GiB Physical Page Bitmap (1 page per bit) + * E480 00000000 - E500 00000000 39 512 GiB Physical Page DblAlloc Bitmap (1 page per bit) + * E500 00000000 - E500 80000000 31 2 GiB Physical Page Super Bitmap (64 pages per bit) * FD00 00000000 - FD80 00000000 39 512 GiB Local APIC * FE00 00000000 - FE80 00000000 39 512 GiB Fractal Mapping (PML4 510) * FE80 00000000 - FF00 00000000 39 512 GiB Temp Fractal Mapping @@ -55,8 +57,11 @@ #define MM_PPD_CFG MM_PPD_BASE #define MM_PPD_VFS (KERNEL_BASE|(0xD008##00000000)) #define MM_USER_CODE (KERNEL_BASE|(0xD080##00000000)) + #define MM_PAGE_COUNTS (KERNEL_BASE|(0xE000##00000000)) -#define MM_PAGE_SUPBMP (KERNEL_BASE|(0xE400##00000000)) +#define MM_PAGE_BITMAP (KERNEL_BASE|(0xE400##00000000)) +#define MM_PAGE_DBLBMP (KERNEL_BASE|(0xE480##00000000)) +#define MM_PAGE_SUPBMP (KERNEL_BASE|(0xE500##00000000)) #define MM_LOCALAPIC (KERNEL_BASE|(0xFD00##00000000)) #define MM_FRACTAL_BASE (KERNEL_BASE|(0xFE00##00000000)) diff --git a/Kernel/arch/x86_64/mm_phys.c b/Kernel/arch/x86_64/mm_phys.c index 92a38f2a..9c7190f9 100644 --- a/Kernel/arch/x86_64/mm_phys.c +++ b/Kernel/arch/x86_64/mm_phys.c @@ -23,6 +23,8 @@ extern void gKernelEnd; // === GLOBALS === tSpinlock glPhysicalPages; Uint64 *gaSuperBitmap; // 1 bit = 64 Pages +Uint64 *gaMainBitmap; // 1 bit = 1 Page +Uint64 *gaMultiBitmap; // Each bit means that the page is being used multiple times Uint32 *gaiPageReferences = (void*)MM_PAGE_COUNTS; // Reference Counts tPAddr giFirstFreePage; // First possibly free page Uint64 giPhysRangeFree[NUM_MM_PHYS_RANGES]; // Number of free pages in each range @@ -76,32 +78,45 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) // - Starting from the end of the kernel // - We also need a region for the super bitmap superPages = ((giMaxPhysPage+64*8-1)/(64*8) + 0xFFF) >> 12; - numPages = (giMaxPhysPage + 7) * sizeof(*gaiPageReferences); + numPages = (giMaxPhysPage + 7) / 8; numPages = (numPages + 0xFFF) >> 12; Log(" MM_InitPhys_Multiboot: numPages = %i", numPages); if(maxAddr == 0) { + int todo = numPages; // Ok, naieve allocation, just put it after the kernel - tVAddr vaddr = MM_PAGE_COUNTS; + // - Allocated Bitmap + tVAddr vaddr = MM_PAGE_BITMAP; tPAddr paddr = (tPAddr)&gKernelEnd - KERNEL_BASE; - while(numPages --) + while(todo --) { MM_Map(vaddr, paddr); vaddr += 0x1000; paddr += 0x1000; } - // Allocate the super bitmap - gaSuperBitmap = (void*) MM_MapHWPages( - paddr, - ((giMaxPhysPage+64*8-1)/(64*8) + 0xFFF) >> 12 - ); + // - Multi-Alloc Bitmap + vaddr = MM_PAGE_DBLBMP; + todo = numPages; + while(todo --) { + MM_Map(vaddr, paddr); + vaddr += 0x1000; + paddr += 0x1000; + } + // - Super Bitmap + vaddr = MM_PAGE_SUPBMP; + todo = superPages; + while(todo --) { + MM_Map(vaddr, paddr); + vaddr += 0x1000; + paddr += 0x1000; + } } // Scan for a nice range else { - int todo = numPages + superPages; + int todo = numPages*2 + superPages; tPAddr paddr = 0; - tVAddr vaddr = MM_PAGE_COUNTS; + tVAddr vaddr = MM_PAGE_BITMAP; // Scan! for( ent = mmapStart; @@ -110,6 +125,7 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) ) { int avail; + int i, max; // RAM only please if( ent->Type != 1 ) @@ -133,30 +149,30 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) } // Map - // - Counts - if( todo ) { - int i, max; - max = todo < avail ? todo : avail; - for( i = 0; i < max; i ++ ) - { - MM_Map(vaddr, paddr); - todo --; - vaddr += 0x1000; - paddr += 0x1000; - } - // Alter the destination address when needed - if(todo == superPages) - vaddr = MM_PAGE_SUPBMP; + max = todo < avail ? todo : avail; + for( i = 0; i < max; i ++ ) + { + MM_Map(vaddr, paddr); + todo --; + vaddr += 0x1000; + paddr += 0x1000; } - else - break; + // 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; } } // Fill the bitmaps // - initialise to one, then clear the avaliable areas - memset(gaSuperBitmap, -1, (giMaxPhysPage+64*8-1)/(64*8)); - memset(gaiPageReferences, -1, giMaxPhysPage*sizeof(*gaiPageReferences)); + memset(gaSuperBitmap, -1, superPages<<12); + memset(gaMainBitmap, -1, numPages<<12); + memset(gaMultiBitmap, 0, numPages<<12); // - Clear all Type=1 areas for( ent = mmapStart; @@ -164,14 +180,44 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ) ) { + Uint64 base, size; // Check if the type is RAM if(ent->Type != 1) continue; - // Clear the range - memset( - &gaiPageReferences[ ent->Base >> 12 ], - 0, - (ent->Size>>12)*sizeof(*gaiPageReferences) - ); + + // Main bitmap + base = ent->Base >> 12; + size = ent->Size >> 12; + + if(base & 63) { + Uint64 val = -1 << (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 = -1 << (size & 7); + val <<= (size/8)&7; + gaMainBitmap[base / 64] &= ~val; + } + + // Super Bitmap + base = ent->Base >> 12; + size = ent->Size >> 12; + size = (size + (base & 63) + 63) >> 6; + base = base >> 6; + if(base & 63) { + Uint64 val = -1 << (base & 63); + gaSuperBitmap[base / 64] &= ~val; + size -= (base & 63); + base += 64 - (base & 63); + } + memset( &gaSuperBitmap[base / 64], 0, size/8 ); + if( size & 7 ) { + Uint64 val = -1 << (size & 7); + val <<= (size/8)&7; + gaSuperBitmap[base / 64] &= ~val; + } } // Reference the used pages @@ -256,7 +302,7 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) continue; } // Check individual page - if( gaiPageReferences[addr] ) { + if( gaMainBitmap[addr >> 6] & (1 << (addr & 63)) ) { nFree = 0; addr ++; continue; @@ -293,7 +339,7 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) addr -= Num; for( i = 0; i < Num; i++ ) { - gaiPageReferences[addr] = 1; + gaiPageReferences[addr >> 6] |= 1 << (addr & 63); if(addr >> 32) rangeID = MM_PHYS_MAX; else if(addr >> 24) rangeID = MM_PHYS_32BIT; @@ -308,14 +354,7 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) Num = (Num + (64-1)) & ~(64-1); for( i = 0; i < Num/64; i++ ) { - int j, bFull = 1; - for( j = 0; j < 64; j ++ ) { - if( gaiPageReferences[addr+i*64+j] ) { - bFull = 0; - break; - } - } - if( bFull ) + if( gaMainBitmap[ addr >> 6 ] == -1 ) gaSuperBitmap[addr>>12] |= 1 << ((addr >> 6) & 64); } @@ -337,19 +376,23 @@ tPAddr MM_AllocPhys(void) */ void MM_RefPhys(tPAddr PAddr) { - int bIsFull, j; + Uint64 page = PAddr >> 12; + if( PAddr >> 12 > giMaxPhysPage ) return ; - gaiPageReferences[ PAddr >> 12 ] ++; - bIsFull = 1; - for( j = 0; j < 64; j++ ) { - if( gaiPageReferences[ PAddr >> 12 ] == 0 ) { - bIsFull = 0; - break; - } + if( gaMainBitmap[ page >> 6 ] & (1 << (page&63)) ) + { + // Reference again + gaMultiBitmap[ page >> 6 ] |= 1 << (page&63); + gaiPageReferences[ page ] ++; + } + else + { + // Allocate + gaMainBitmap[page >> 6] |= 1 << (page&63); + if( gaMainBitmap[page >> 6 ] == -1 ) + gaSuperBitmap[page>> 12] |= 1 << ((page >> 6) & 63); } - if( bIsFull ) - gaSuperBitmap[PAddr >> 24] |= 1 << ((PAddr >> 18) & 64); } /** @@ -357,10 +400,21 @@ void MM_RefPhys(tPAddr PAddr) */ void MM_DerefPhys(tPAddr PAddr) { + Uint64 page = PAddr >> 12; + if( PAddr >> 12 > giMaxPhysPage ) return ; - gaiPageReferences[ PAddr >> 12 ] --; - if( gaiPageReferences[ PAddr >> 12 ] ) - { - gaSuperBitmap[PAddr >> 24] &= ~(1 << ((PAddr >> 18) & 64)); + + if( gaMultiBitmap[ page >> 6 ] & (1 << (page&63)) ) { + gaiPageReferences[ page ] --; + if( gaiPageReferences[ page ] == 1 ) + gaMultiBitmap[ page >> 6 ] &= ~(1 << (page&63)); + if( gaiPageReferences[ page ] == 0 ) + gaMainBitmap[ page >> 6 ] &= ~(1 << (page&63)); + } + else + gaMainBitmap[ page >> 6 ] &= ~(1 << (page&63)); + + if(gaMainBitmap[ page >> 6 ] == 0) { + gaSuperBitmap[page >> 12] &= ~(1 << ((page >> 6) & 63)); } } -- 2.20.1