From 375dd210e083ab233903ba3804ad629fc7365189 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 29 May 2010 11:19:25 +0800 Subject: [PATCH] Chicken and egg problem, solved --- Kernel/Makefile.BuildNum | 2 +- Kernel/arch/x86_64/errors.c | 6 +- Kernel/arch/x86_64/include/mm_virt.h | 8 +-- Kernel/arch/x86_64/mm_phys.c | 104 +++++++++++++++------------ Kernel/arch/x86_64/mm_virt.c | 27 ++++--- 5 files changed, 84 insertions(+), 63 deletions(-) diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index 74050b66..e1fa0fbe 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 2277 +BUILD_NUM = 2287 diff --git a/Kernel/arch/x86_64/errors.c b/Kernel/arch/x86_64/errors.c index e66d550c..1c68b184 100644 --- a/Kernel/arch/x86_64/errors.c +++ b/Kernel/arch/x86_64/errors.c @@ -33,12 +33,14 @@ void Error_Handler(tRegs *Regs) Log(" SS:RSP = 0x%04x:%016x", Regs->SS, Regs->RSP); Log(" RFLAGS = 0x%016x", Regs->RFlags); - Log(" EAX %016x ECX %016x EDX %016x EBX %016x", + Log(" RAX %016x RCX %016x RDX %016x RBX %016x", Regs->RAX, Regs->RCX, Regs->RDX, Regs->RBX); - Log(" ESP %016x EBP %016x ESI %016x EDI %016x", + Log(" RSP %016x RBP %016x RSI %016x RDI %016x", Regs->RSP, Regs->RBP, Regs->RSP, Regs->RDI); Log(" R8 %016x R9 %016x R10 %016x R11 %016x", Regs->R8, Regs->R9, Regs->R10, Regs->R11); + Log(" R12 %016x R13 %016x R14 %016x R15 %016x", + Regs->R12, Regs->R13, Regs->R14, Regs->R15); Log(" FS %04x GS %04x", Regs->FS, Regs->GS); diff --git a/Kernel/arch/x86_64/include/mm_virt.h b/Kernel/arch/x86_64/include/mm_virt.h index baade6ea..5221e511 100644 --- a/Kernel/arch/x86_64/include/mm_virt.h +++ b/Kernel/arch/x86_64/include/mm_virt.h @@ -38,11 +38,11 @@ */ #define MM_USER_MIN 0x00000000##00010000 -#define USER_LIB_MAX 0x00008000##00000000 +#define USER_LIB_MAX 0x00007000##00000000 #define USER_STACK_SZ 0x00000000##00020000 // 64 KiB -#define USER_STACK_TOP 0x00008FFF##FFFFF000 -#define MM_USER_MAX 0x00008FFF##FFFFF000 -//#define KERNEL_BASE 0xFFF8000##00000000 +#define USER_STACK_TOP 0x00007FFF##FFFFF000 +#define MM_USER_MAX 0x00007FFF##FFFFF000 +//#define KERNEL_BASE 0xFFFF8000##00000000 #define MM_KHEAP_BASE (KERNEL_BASE|(0x8000##80000000)) #define MM_KHEAP_MAX (KERNEL_BASE|(0x9000##00000000)) #define MM_MODULE_MIN (KERNEL_BASE|(0x9000##00000000)) diff --git a/Kernel/arch/x86_64/mm_phys.c b/Kernel/arch/x86_64/mm_phys.c index 47fea403..3f5df375 100644 --- a/Kernel/arch/x86_64/mm_phys.c +++ b/Kernel/arch/x86_64/mm_phys.c @@ -32,6 +32,11 @@ 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 +// 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 +#define NUM_STATIC_ALLOC 3 +tPAddr gaiStaticAllocPages[NUM_STATIC_ALLOC] = {0}; // === CODE === /** @@ -46,7 +51,7 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) int i; Uint64 base, size; tVAddr vaddr; - tPAddr paddr; + tPAddr paddr, firstFreePage; Log("MM_InitPhys_Multiboot: (MBoot=%p)", MBoot); @@ -91,40 +96,38 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) numPages, superPages); if(maxAddr == 0) { - int todo = numPages; + 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(todo ) { + // Allocate statics + for( i = 0; i < NUM_STATIC_ALLOC; i++) { + if(gaiStaticAllocPages[i] != 0) continue; + gaiStaticAllocPages[i] = paddr; + paddr += 0x1000; + } + MM_Map(vaddr, paddr); vaddr += 0x1000; paddr += 0x1000; - } - // - 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; + + todo --; + + if( todo == numPages + superPages ) + vaddr = MM_PAGE_DBLBMP; + if( todo == superPages ) + vaddr = MM_PAGE_SUPBMP; } } // Scan for a nice range else { int todo = numPages*2 + superPages; - tPAddr paddr = 0; - tVAddr vaddr = MM_PAGE_BITMAP; + paddr = 0; + vaddr = MM_PAGE_BITMAP; // Scan! for( ent = mmapStart; @@ -133,7 +136,6 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) ) { int avail; - int i, max; // RAM only please if( ent->Type != 1 ) @@ -161,13 +163,23 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) Log(" MM_InitPhys_Multiboot: paddr=0x%x, avail=%i", paddr, avail); // Map - max = todo < avail ? todo : avail; - for( i = 0; i < max; i ++ ) + 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; @@ -179,8 +191,10 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) if( !todo ) break; } } + // Save the current value of paddr to simplify the allocation later + firstFreePage = paddr; - Log(" MM_InitPhys_Multiboot: Cearing multi bitmap"); + Log(" MM_InitPhys_Multiboot: Clearing multi bitmap"); // Fill the bitmaps memset(gaMultiBitmap, 0, numPages<<12); // - initialise to one, then clear the avaliable areas @@ -228,35 +242,20 @@ void MM_InitPhys_Multiboot(tMBoot_Info *MBoot) } // Reference the used pages - // - Kernel - Log(" MM_InitPhys_Multiboot: Setting kernel area"); base = (tPAddr)&gKernelBase >> 12; - size = ((tPAddr)&gKernelEnd - KERNEL_BASE - base) >> 12; + size = firstFreePage >> 12; memset( &gaMainBitmap[base / 64], -1, size/8 ); if( size & 7 ) { Uint64 val = -1 << (size & 7); val <<= (size/8)&7; gaMainBitmap[base / 64] |= val; } - // - Bitmaps - Log(" MM_InitPhys_Multiboot: Setting bitmaps' memory"); - vaddr = MM_PAGE_BITMAP; - for( i = 0; i < numPages; i++, vaddr ++ ) - { - paddr = MM_GetPhysAddr(vaddr) >> 12; - gaMainBitmap[paddr >> 6] |= 1 << (paddr&63); - } - vaddr = MM_PAGE_DBLBMP; - for( i = 0; i < numPages; i++, vaddr += 0x1000 ) - { - paddr = MM_GetPhysAddr(vaddr) >> 12; - gaMainBitmap[paddr >> 6] |= 1 << (paddr&63); - } - vaddr = MM_PAGE_SUPBMP; - for( i = 0; i < superPages; i++, vaddr += 0x1000 ) - { - paddr = MM_GetPhysAddr(vaddr) >> 12; - gaMainBitmap[paddr >> 6] |= 1 << (paddr&63); + // Free the unused static allocs + for( i = 0; i < NUM_STATIC_ALLOC; i++) { + if(gaiStaticAllocPages[i] != 0) + continue; + gaMainBitmap[ gaiStaticAllocPages[i] >> (12+6) ] + &= ~(1 << ((gaiStaticAllocPages[i]>>12)&63)); } // Fill the super bitmap @@ -412,6 +411,17 @@ tPAddr MM_AllocPhysRange(int Num, int Bits) */ tPAddr MM_AllocPhys(void) { + int i; + + // Hack to allow allocation during setup + for(i = 0; i < NUM_STATIC_ALLOC; i++) { + if( gaiStaticAllocPages[i] ) { + tPAddr ret = gaiStaticAllocPages[i]; + gaiStaticAllocPages[i] = 0; + return ret; + } + } + return MM_AllocPhysRange(1, -1); } diff --git a/Kernel/arch/x86_64/mm_virt.c b/Kernel/arch/x86_64/mm_virt.c index cf00f6e2..be539dbf 100644 --- a/Kernel/arch/x86_64/mm_virt.c +++ b/Kernel/arch/x86_64/mm_virt.c @@ -13,6 +13,10 @@ #define PTAB_SHIFT 12 #define PADDR_MASK 0x7FFFFFFF##FFFFF000 +#define PAGE_MASK (((Uint)1 << 36)-1) +#define TABLE_MASK (((Uint)1 << 27)-1) +#define PDP_MASK (((Uint)1 << 18)-1) +#define PML4_MASK (((Uint)1 << 9)-1) #define PF_PRESENT 0x1 #define PF_WRITE 0x2 @@ -22,10 +26,10 @@ #define PF_NX 0x80000000##00000000 // === MACROS === -#define PAGETABLE(idx) (*((tPAddr*)MM_FRACTAL_BASE+(idx))) -#define PAGEDIR(idx) PAGETABLE((MM_FRACTAL_BASE>>12)+((idx)&0x7FFFFFF)) -#define PAGEDIRPTR(idx) PAGEDIR((MM_FRACTAL_BASE>>21)+((idx)&0x3FFFF)) -#define PAGEMAPLVL4(idx) PAGEDIRPTR((MM_FRACTAL_BASE>>30)+((idx)&0x1FF)) +#define PAGETABLE(idx) (*((tPAddr*)MM_FRACTAL_BASE+((idx)&PAGE_MASK))) +#define PAGEDIR(idx) PAGETABLE((MM_FRACTAL_BASE>>12)+((idx)&TABLE_MASK)) +#define PAGEDIRPTR(idx) PAGEDIR((MM_FRACTAL_BASE>>21)+((idx)&PDP_MASK)) +#define PAGEMAPLVL4(idx) PAGEDIRPTR((MM_FRACTAL_BASE>>30)+((idx)&PML4_MASK)) // === GLOBALS === @@ -50,6 +54,11 @@ int MM_Map(tVAddr VAddr, tPAddr PAddr) Log("MM_Map: (VAddr=0x%x, PAddr=0x%x)", VAddr, PAddr); // Check PML4 + Log(" MM_Map: &PAGEMAPLVL4(%x) = %x", VAddr >> 39, &PAGEMAPLVL4(VAddr >> 39)); + Log(" MM_Map: &PAGEDIRPTR(%x) = %x", VAddr >> 30, &PAGEDIRPTR(VAddr >> 30)); + Log(" MM_Map: &PAGEDIR(%x) = %x", VAddr >> 21, &PAGEDIR(VAddr >> 21)); + Log(" MM_Map: &PAGETABLE(%x) = %x", VAddr >> 12, &PAGETABLE(VAddr >> 12)); + Log(" MM_Map: &PAGETABLE(0) = %x", &PAGETABLE(0)); if( !(PAGEMAPLVL4(VAddr >> 39) & 1) ) { tmp = MM_AllocPhys(); @@ -77,10 +86,10 @@ int MM_Map(tVAddr VAddr, tPAddr PAddr) } // Check if this virtual address is already mapped - if( PAGETABLE(VAddr >> 12) & 1 ) + if( PAGETABLE(VAddr >> PTAB_SHIFT) & 1 ) return 0; - PAGETABLE(VAddr >> 12) = PAddr | 3; + PAGETABLE(VAddr >> PTAB_SHIFT) = PAddr | 3; return 1; } @@ -97,7 +106,7 @@ void MM_Unmap(tVAddr VAddr) // Check Page Dir if( !(PAGEDIR(VAddr >> 21) & 1) ) return ; - PAGETABLE(VAddr >> 12) = 0; + PAGETABLE(VAddr >> PTAB_SHIFT) = 0; } /** @@ -150,11 +159,11 @@ tPAddr MM_GetPhysAddr(tVAddr Addr) if( !(PAGEDIR(Addr >> 21) & 1) ) return 0; Log(" MM_GetPhysAddr: PT Valid"); - if( !(PAGETABLE(Addr >> 12) & 1) ) + if( !(PAGETABLE(Addr >> PTAB_SHIFT) & 1) ) return 0; Log(" MM_GetPhysAddr: Page Valid"); - return (PAGETABLE(Addr >> 12) & ~0xFFF) | (Addr & 0xFFF); + return (PAGETABLE(Addr >> PTAB_SHIFT) & ~0xFFF) | (Addr & 0xFFF); } /** -- 2.20.1