X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Farch%2Fx86%2Fmm_virt.c;h=a62397484fb44c0002c90ad0a839ff10c49711c4;hb=2462d860630674d10d554f86aa669163f6f2db6b;hp=13562f2853560af1fed15dc48dca13cc77059c05;hpb=b806b8f55067584cb90fe20277235369a1111c66;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/arch/x86/mm_virt.c b/KernelLand/Kernel/arch/x86/mm_virt.c index 13562f28..a6239748 100644 --- a/KernelLand/Kernel/arch/x86/mm_virt.c +++ b/KernelLand/Kernel/arch/x86/mm_virt.c @@ -17,6 +17,7 @@ #include #include #include +#include #define TAB 22 @@ -97,6 +98,7 @@ tPAddr MM_DuplicatePage(tVAddr VAddr); #define gaPAE_TmpPDPT ((tTabEnt*)PAE_TMP_PDPT_ADDR) int gbUsePAE = 0; tMutex glTempMappings; +tSemaphore gTempMappingsSem; tMutex glTempFractal; Uint32 gWorkerStacks[(NUM_WORKER_STACKS+31)/32]; int giLastUsedWorker = 0; @@ -117,6 +119,8 @@ void MM_PreinitVirtual(void) { gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3; INVLPG( PAGE_TABLE_ADDR ); + + Semaphore_Init(&gTempMappingsSem, NUM_TEMP_PAGES, NUM_TEMP_PAGES, "MMVirt", "Temp Mappings"); } /** @@ -125,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 @@ -143,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 ); } @@ -414,7 +416,7 @@ void MM_Deallocate(tVAddr VAddr) * \fn tPAddr MM_GetPhysAddr(tVAddr Addr) * \brief Checks if the passed address is accesable */ -tPAddr MM_GetPhysAddr(const void *Addr) +tPAddr MM_GetPhysAddr(volatile const void *Addr) { tVAddr addr = (tVAddr)Addr; if( !(gaPageDir[addr >> 22] & 1) ) @@ -749,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++) @@ -770,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); @@ -781,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) ); @@ -788,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; } @@ -978,34 +986,32 @@ 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) { - int i; - - //ENTER("XPAddr", PAddr); + ENTER("PPAddr", PAddr); PAddr &= ~0xFFF; - //LOG("glTempMappings = %i", glTempMappings); - - for(;;) + if( Semaphore_Wait(&gTempMappingsSem, 1) != 1 ) + return NULL; + LOG("Semaphore good"); + Mutex_Acquire( &glTempMappings ); + for( int i = 0; i < NUM_TEMP_PAGES; i ++ ) { - Mutex_Acquire( &glTempMappings ); - - for( i = 0; i < NUM_TEMP_PAGES; i ++ ) - { - // Check if page used - if(gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ] & 1) continue; - // Mark as used - gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ] = PAddr | 3; - INVLPG( TEMP_MAP_ADDR + (i << 12) ); - //LEAVE('p', TEMP_MAP_ADDR + (i << 12)); - Mutex_Release( &glTempMappings ); - return (void*)( TEMP_MAP_ADDR + (i << 12) ); - } + Uint32 *pte = &gaPageTable[ (TEMP_MAP_ADDR >> 12) + i ]; + LOG("%i: %x", i, *pte); + // Check if page used + if(*pte & 1) continue; + // Mark as used + *pte = PAddr | 3; + INVLPG( TEMP_MAP_ADDR + (i << 12) ); + LEAVE('p', TEMP_MAP_ADDR + (i << 12)); Mutex_Release( &glTempMappings ); - Threads_Yield(); // TODO: Use a sleep queue here instead + return (void*)( TEMP_MAP_ADDR + (i << 12) ); } + Mutex_Release( &glTempMappings ); + Log_KernelPanic("MMVirt", "Semaphore suplied a mapping, but none are avaliable"); + return NULL; } /** @@ -1017,8 +1023,10 @@ void MM_FreeTemp(void *VAddr) int i = (tVAddr)VAddr >> 12; //ENTER("xVAddr", VAddr); - if(i >= (TEMP_MAP_ADDR >> 12)) + if(i >= (TEMP_MAP_ADDR >> 12)) { gaPageTable[ i ] = 0; + Semaphore_Signal(&gTempMappingsSem, 1); + } //LEAVE('-'); } @@ -1027,14 +1035,19 @@ void MM_FreeTemp(void *VAddr) * \fn tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) * \brief Allocates a contigous number of pages */ -tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) +void *MM_MapHWPages(tPAddr PAddr, Uint Number) { - int i, j; + int j; PAddr &= ~0xFFF; - + + if( PAddr < 1024*1024 && (1024*1024-PAddr) >= Number * PAGE_SIZE ) + { + return (void*)(KERNEL_BASE + PAddr); + } + // Scan List - for( i = 0; i < NUM_HW_PAGES; i ++ ) + for( int i = 0; i < NUM_HW_PAGES; i ++ ) { // Check if addr used if( gaPageTable[ (HW_MAP_ADDR >> 12) + i ] & 1 ) @@ -1054,7 +1067,7 @@ tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) MM_RefPhys( PAddr + (j<<12) ); gaPageTable[ (HW_MAP_ADDR >> 12) + i + j ] = (PAddr + (j<<12)) | 3; } - return HW_MAP_ADDR + (i<<12); + return (void*)(HW_MAP_ADDR + (i<<12)); } } // If we don't find any, return NULL @@ -1069,10 +1082,10 @@ tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) * \param PhysAddr Pointer to the location to place the physical address allocated * \return Virtual address allocate */ -tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) +void *MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) { tPAddr phys; - tVAddr ret; + void *ret; ENTER("iPages iMaxBits pPhysAddr", Pages, MaxBits, PhysAddr); @@ -1101,7 +1114,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) return 0; } LEAVE('x', ret); - return ret; + return (void*)ret; } // Slow Allocate @@ -1125,7 +1138,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) if( PhysAddr ) *PhysAddr = phys; LEAVE('x', ret); - return ret; + return (void*)ret; } /** @@ -1137,7 +1150,11 @@ void MM_UnmapHWPages(tVAddr VAddr, Uint Number) int i, j; //Log_Debug("VirtMem", "MM_UnmapHWPages: (VAddr=0x%08x, Number=%i)", VAddr, Number); - + + // + if( KERNEL_BASE <= VAddr && VAddr < KERNEL_BASE + 1024*1024 ) + return ; + // Sanity Check if(VAddr < HW_MAP_ADDR || VAddr+Number*0x1000 > HW_MAP_MAX) return;