From aa62597b70c3f3753ee21b174ca695b6b6c4cdef Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 21 Dec 2013 17:35:34 +0800 Subject: [PATCH] Kernel/x86 - Fix PMem bitmap overflow --- KernelLand/Kernel/arch/x86/main.c | 3 +- KernelLand/Kernel/arch/x86/mm_phys.c | 26 +++++++++++++---- KernelLand/Kernel/arch/x86/mm_virt.c | 43 ++++++++++++++++------------ KernelLand/Kernel/arch/x86/proc.c | 13 +++++++-- 4 files changed, 56 insertions(+), 29 deletions(-) diff --git a/KernelLand/Kernel/arch/x86/main.c b/KernelLand/Kernel/arch/x86/main.c index 822bf70b..93470a44 100644 --- a/KernelLand/Kernel/arch/x86/main.c +++ b/KernelLand/Kernel/arch/x86/main.c @@ -9,6 +9,7 @@ #include #include #include +#include #define VGA_ERRORS 0 @@ -87,7 +88,7 @@ int kmain(Uint MbMagic, void *MbInfoPtr) MbMagic, MULTIBOOT_MAGIC, MULTIBOOT2_MAGIC); return 0; } - + // Set up physical memory manager MM_Install(nPMemMapEnts, pmemmap); diff --git a/KernelLand/Kernel/arch/x86/mm_phys.c b/KernelLand/Kernel/arch/x86/mm_phys.c index 37166a01..eb422c96 100644 --- a/KernelLand/Kernel/arch/x86/mm_phys.c +++ b/KernelLand/Kernel/arch/x86/mm_phys.c @@ -7,6 +7,7 @@ #include #include #include +#include //#define USE_STACK 1 #define TRACE_ALLOCS 0 // Print trace messages on AllocPhys/DerefPhys @@ -41,11 +42,10 @@ void **gaPageNodes = (void*)MM_PAGENODE_BASE; // === CODE === void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) { - Uint i; Uint64 maxAddr = 0; // --- Find largest address - for( i = 0; i < NPMemRanges; i ++ ) + for( Uint i = 0; i < NPMemRanges; i ++ ) { tPMemMapEnt *ent = &PMemRanges[i]; // If entry is RAM and is above `maxAddr`, change `maxAddr` @@ -56,20 +56,33 @@ void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) giTotalMemorySize += ent->Length >> 12; } } + LOG("giTotalMemorySize = %lli KiB", giTotalMemorySize*4); + LOG("maxAddr = 0x%X", maxAddr); + + // Clip to 32-bits + if( maxAddr > (1ULL << 32) ) { + maxAddr = (1ULL << 32); + } giPageCount = maxAddr >> 12; giLastPossibleFree = giPageCount - 1; - memsetd(gaPageBitmap, 0xFFFFFFFF, giPageCount/32); // Set up allocateable space - for( i = 0; i < NPMemRanges; i ++ ) + for( Uint i = 0; i < NPMemRanges; i ++ ) { tPMemMapEnt *ent = &PMemRanges[i]; if( ent->Type == PMEMTYPE_FREE ) { Uint64 startpg = ent->Start / PAGE_SIZE; Uint64 pgcount = ent->Length / PAGE_SIZE; + // Ignore start addresses >32 bits + if( startpg > (1 << 20) ) + continue ; + // Clip lengths to 32-bit address space + if( startpg + pgcount > (1<<20) ) + pgcount = (1<<20) - startpg; + while( startpg % 32 && pgcount ) { gaPageBitmap[startpg/32] &= ~(1U << (startpg%32)); startpg ++; @@ -86,13 +99,14 @@ void MM_Install(int NPMemRanges, tPMemMapEnt *PMemRanges) } else if( ent->Type == PMEMTYPE_USED ) { + // TODO: Clip? giPhysAlloc += ent->Length / PAGE_SIZE; } } // Fill Superpage bitmap // - A set bit means that there are no free pages in this block of 32 - for( i = 0; i < (giPageCount+31)/32; i ++ ) + for( Uint i = 0; i < (giPageCount+31)/32; i ++ ) { if( gaPageBitmap[i] + 1 == 0 ) { gaSuperBitmap[i/32] |= (1 << i%32); @@ -239,7 +253,7 @@ tPAddr MM_AllocPhys(void) // Release Spinlock Mutex_Release( &glPhysAlloc ); - LEAVE('X', ret); + LEAVE('P', ret); #if TRACE_ALLOCS if( now() > 4000 ) { diff --git a/KernelLand/Kernel/arch/x86/mm_virt.c b/KernelLand/Kernel/arch/x86/mm_virt.c index b81698c3..a6239748 100644 --- a/KernelLand/Kernel/arch/x86/mm_virt.c +++ b/KernelLand/Kernel/arch/x86/mm_virt.c @@ -129,10 +129,8 @@ void MM_PreinitVirtual(void) */ void MM_InstallVirtual(void) { - int i; - // --- Pre-Allocate kernel tables - for( i = KERNEL_BASE>>22; i < 1024; i ++ ) + for( int i = KERNEL_BASE>>22; i < 1024; i ++ ) { if( gaPageDir[ i ] ) continue; // Skip stack tables, they are process unique @@ -147,7 +145,7 @@ void MM_InstallVirtual(void) } // Unset kernel on the User Text pages - for( i = ((tVAddr)&_UsertextEnd-(tVAddr)&_UsertextBase+0xFFF)/4096; i--; ) { + for( int i = ((tVAddr)&_UsertextEnd-(tVAddr)&_UsertextBase+0xFFF)/4096; i--; ) { MM_SetFlags( (tVAddr)&_UsertextBase + i*4096, 0, MM_PFLAG_KERNEL ); } @@ -753,10 +751,10 @@ tVAddr MM_NewKStack(void) */ tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize) { - Uint base, addr; - tVAddr tmpPage; + Uint base; tPAddr page; + LOG("(StackContents=%p,ContentsSize=%i)", StackContents, ContentsSize); // TODO: Thread safety // Find a free worker stack address for(base = giLastUsedWorker; base < NUM_WORKER_STACKS; base++) @@ -774,9 +772,10 @@ tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize) break; } if(base >= NUM_WORKER_STACKS) { - Warning("Uh-oh! Out of worker stacks"); + Log_Error("MMVirt", "Uh-oh! Out of worker stacks"); return 0; } + LOG("base=0x%x", base); // It's ours now! gWorkerStacks[base/32] |= (1 << base); @@ -785,6 +784,7 @@ tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize) // We have one base = WORKER_STACKS + base * WORKER_STACK_SIZE; //Log(" MM_NewWorkerStack: base = 0x%x", base); + LOG("base=%p (top)", base); // Set the temp fractals to TID0's address space GET_TEMP_MAPPING( ((Uint)gaInitPageDir - KERNEL_BASE) ); @@ -792,29 +792,33 @@ tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize) // Check if the directory is mapped (we are assuming that the stacks // will fit neatly in a directory) - //Log(" MM_NewWorkerStack: gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]); + LOG("gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]); if(gaTmpDir[ base >> 22 ] == 0) { gaTmpDir[ base >> 22 ] = MM_AllocPhys() | 3; INVLPG( &gaTmpTable[ (base>>12) & ~0x3FF ] ); } // Mapping Time! - for( addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 ) + for( Uint addr = 0; addr < WORKER_STACK_SIZE; addr += 0x1000 ) { page = MM_AllocPhys(); gaTmpTable[ (base + addr) >> 12 ] = page | 3; } + LOG("mapped"); // Release temporary fractal REL_TEMP_MAPPING(); // NOTE: Max of 1 page // `page` is the last allocated page from the previious for loop - tmpPage = (tVAddr)MM_MapTemp( page ); - memcpy( (void*)( tmpPage + (0x1000 - ContentsSize) ), StackContents, ContentsSize); - MM_FreeTemp( (void*)tmpPage ); + LOG("Mapping first page"); + char *tmpPage = MM_MapTemp( page ); + LOG("tmpPage=%p", tmpPage); + memcpy( tmpPage + (0x1000 - ContentsSize), StackContents, ContentsSize); + MM_FreeTemp( tmpPage ); //Log("MM_NewWorkerStack: RETURN 0x%x", base); + LOG("return %p", base+WORKER_STACK_SIZE); return base + WORKER_STACK_SIZE; } @@ -982,25 +986,26 @@ tPAddr MM_DuplicatePage(tVAddr VAddr) * \brief Create a temporary memory mapping * \todo Show Luigi Barone (C Lecturer) and see what he thinks */ -void * MM_MapTemp(tPAddr PAddr) +void *MM_MapTemp(tPAddr PAddr) { - //ENTER("XPAddr", PAddr); + ENTER("PPAddr", PAddr); PAddr &= ~0xFFF; - //LOG("glTempMappings = %i", glTempMappings); - if( Semaphore_Wait(&gTempMappingsSem, 1) != 1 ) return NULL; + LOG("Semaphore good"); Mutex_Acquire( &glTempMappings ); for( int i = 0; i < NUM_TEMP_PAGES; i ++ ) { + Uint32 *pte = &gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ]; + LOG("%i: %x", i, *pte); // Check if page used - if(gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ] & 1) continue; + if(*pte & 1) continue; // Mark as used - gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ] = PAddr | 3; + *pte = PAddr | 3; INVLPG( TEMP_MAP_ADDR + (i << 12) ); - //LEAVE('p', TEMP_MAP_ADDR + (i << 12)); + LEAVE('p', TEMP_MAP_ADDR + (i << 12)); Mutex_Release( &glTempMappings ); return (void*)( TEMP_MAP_ADDR + (i << 12) ); } diff --git a/KernelLand/Kernel/arch/x86/proc.c b/KernelLand/Kernel/arch/x86/proc.c index 3119ada1..2869c3c3 100644 --- a/KernelLand/Kernel/arch/x86/proc.c +++ b/KernelLand/Kernel/arch/x86/proc.c @@ -1,7 +1,11 @@ /* - * AcessOS Microkernel Version + * Acess2 Kernel (x86) + * - By John Hodge (thePowersGang) + * * proc.c + * - Low level thread management */ +#define DEBUG 0 #include #include #include @@ -505,11 +509,12 @@ tPID Proc_Clone(Uint Flags) */ tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data) { - tThread *new; Uint stack_contents[4]; + LOG("(Fcn=%p,Data=%p)", Fcn, Data); // Create new thread - new = Threads_CloneThreadZero(); + tThread *new = Threads_CloneThreadZero(); + LOG("new=%p", new); if(!new) { Warning("Proc_SpawnWorker - Out of heap space!\n"); return NULL; @@ -523,6 +528,7 @@ tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data) // Create a new worker stack (in PID0's address space) new->KernelStack = MM_NewWorkerStack(stack_contents, sizeof(stack_contents)); + LOG("new->KernelStack = %p", new->KernelStack); // Save core machine state new->SavedState.ESP = new->KernelStack - sizeof(stack_contents); @@ -533,6 +539,7 @@ tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data) // Mark as active new->Status = THREAD_STAT_PREINIT; Threads_AddActive( new ); + LOG("Added to active"); return new; } -- 2.20.1