Kernel/x86 - Fix PMem bitmap overflow
authorJohn Hodge <[email protected]>
Sat, 21 Dec 2013 09:35:34 +0000 (17:35 +0800)
committerJohn Hodge <[email protected]>
Sat, 21 Dec 2013 09:35:34 +0000 (17:35 +0800)
KernelLand/Kernel/arch/x86/main.c
KernelLand/Kernel/arch/x86/mm_phys.c
KernelLand/Kernel/arch/x86/mm_virt.c
KernelLand/Kernel/arch/x86/proc.c

index 822bf70..93470a4 100644 (file)
@@ -9,6 +9,7 @@
 #include <init.h>
 #include <mm_virt.h>
 #include <pmemmap.h>
+#include <semaphore.h>
 
 #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);
        
index 37166a0..eb422c9 100644 (file)
@@ -7,6 +7,7 @@
 #include <mm_virt.h>
 #include <pmemmap.h>
 #include <hal_proc.h>
+#include <semaphore.h>
 
 //#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 ) {
index b81698c..a623974 100644 (file)
@@ -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) );
        }
index 3119ada..2869c3c 100644 (file)
@@ -1,7 +1,11 @@
 /*
- * AcessOS Microkernel Version
+ * Acess2 Kernel (x86)
+ * - By John Hodge (thePowersGang)
+ *
  * proc.c
+ * - Low level thread management
  */
+#define DEBUG  0
 #include <acess.h>
 #include <threads.h>
 #include <proc.h>
@@ -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;
 }

UCC git Repository :: git.ucc.asn.au