X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Farch%2Fx86%2Fmm_virt.c;h=b81698c30f4066fb15b15527220bf14b3805b983;hb=e7a76b0d8a0cc6aa77966509780973a6f8216ef7;hp=c17b57bdd71dfbce2a5ce7378c134f7a3cf4a0e2;hpb=934d0f535e1929fd90ae0606e77794484aa55284;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/arch/x86/mm_virt.c b/KernelLand/Kernel/arch/x86/mm_virt.c index c17b57bd..b81698c3 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"); } /** @@ -414,13 +418,14 @@ void MM_Deallocate(tVAddr VAddr) * \fn tPAddr MM_GetPhysAddr(tVAddr Addr) * \brief Checks if the passed address is accesable */ -tPAddr MM_GetPhysAddr(tVAddr Addr) +tPAddr MM_GetPhysAddr(volatile const void *Addr) { - if( !(gaPageDir[Addr >> 22] & 1) ) + tVAddr addr = (tVAddr)Addr; + if( !(gaPageDir[addr >> 22] & 1) ) return 0; - if( !(gaPageTable[Addr >> 12] & 1) ) + if( !(gaPageTable[addr >> 12] & 1) ) return 0; - return (gaPageTable[Addr >> 12] & ~0xFFF) | (Addr & 0xFFF); + return (gaPageTable[addr >> 12] & ~0xFFF) | (addr & 0xFFF); } /** @@ -441,7 +446,8 @@ int MM_Map(tVAddr VAddr, tPAddr PAddr) //ENTER("xVAddr xPAddr", VAddr, PAddr); // Sanity check if( PAddr & 0xFFF || VAddr & 0xFFF ) { - Log_Warning("MM_Virt", "MM_Map - Physical or Virtual Addresses are not aligned"); + Log_Warning("MM_Virt", "MM_Map - Physical or Virtual Addresses are not aligned (0x%P and %p)", + PAddr, VAddr); //LEAVE('i', 0); return 0; } @@ -693,9 +699,9 @@ tPAddr MM_Clone(int bNoUserCopy) MM_RefPhys( gaTmpTable[i*1024+j] & ~0xFFF ); - tmp = (void *) MM_MapTemp( gaTmpTable[i*1024+j] & ~0xFFF ); + tmp = MM_MapTemp( gaTmpTable[i*1024+j] & ~0xFFF ); memcpy( tmp, (void *)( (i*1024+j)*0x1000 ), 0x1000 ); - MM_FreeTemp( (Uint)tmp ); + MM_FreeTemp( tmp ); } } @@ -716,7 +722,8 @@ tVAddr MM_NewKStack(void) for(base = MM_KERNEL_STACKS; base < MM_KERNEL_STACKS_END; base += MM_KERNEL_STACK_SIZE) { // Check if space is free - if(MM_GetPhysAddr(base) != 0) continue; + if(MM_GetPhysAddr( (void*) base) != 0) + continue; // Allocate //for(i = MM_KERNEL_STACK_SIZE; i -= 0x1000 ; ) for(i = 0; i < MM_KERNEL_STACK_SIZE; i += 0x1000 ) @@ -803,9 +810,9 @@ tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize) // NOTE: Max of 1 page // `page` is the last allocated page from the previious for loop - tmpPage = MM_MapTemp( page ); + tmpPage = (tVAddr)MM_MapTemp( page ); memcpy( (void*)( tmpPage + (0x1000 - ContentsSize) ), StackContents, ContentsSize); - MM_FreeTemp(tmpPage); + MM_FreeTemp( (void*)tmpPage ); //Log("MM_NewWorkerStack: RETURN 0x%x", base); return base + WORKER_STACK_SIZE; @@ -934,7 +941,7 @@ int MM_IsValidBuffer(tVAddr Addr, size_t Size) tPAddr MM_DuplicatePage(tVAddr VAddr) { tPAddr ret; - Uint temp; + void *temp; int wasRO = 0; //ENTER("xVAddr", VAddr); @@ -959,7 +966,7 @@ tPAddr MM_DuplicatePage(tVAddr VAddr) // Copy Data temp = MM_MapTemp(ret); - memcpy( (void*)temp, (void*)VAddr, 0x1000 ); + memcpy( temp, (void*)VAddr, 0x1000 ); MM_FreeTemp(temp); // Restore Writeable status @@ -975,47 +982,46 @@ tPAddr MM_DuplicatePage(tVAddr VAddr) * \brief Create a temporary memory mapping * \todo Show Luigi Barone (C Lecturer) and see what he thinks */ -tVAddr MM_MapTemp(tPAddr PAddr) +void * MM_MapTemp(tPAddr PAddr) { - int i; - //ENTER("XPAddr", PAddr); PAddr &= ~0xFFF; //LOG("glTempMappings = %i", glTempMappings); - for(;;) + if( Semaphore_Wait(&gTempMappingsSem, 1) != 1 ) + return NULL; + 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 TEMP_MAP_ADDR + (i << 12); - } + // 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 ); - 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; } /** * \fn void MM_FreeTemp(tVAddr PAddr) * \brief Free's a temp mapping */ -void MM_FreeTemp(tVAddr VAddr) +void MM_FreeTemp(void *VAddr) { - int i = VAddr >> 12; + 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('-'); } @@ -1024,14 +1030,19 @@ void MM_FreeTemp(tVAddr 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 ) @@ -1051,7 +1062,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 @@ -1066,32 +1077,31 @@ 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 maxCheck = (1 << MaxBits); tPAddr phys; - tVAddr ret; + void *ret; ENTER("iPages iMaxBits pPhysAddr", Pages, MaxBits, PhysAddr); + if(MaxBits == -1) + MaxBits = PHYS_BITS; + // Sanity Check - if(MaxBits < 12 || !PhysAddr) { + if(MaxBits < 12) { LEAVE('i', 0); return 0; } - // Bound - if(MaxBits >= PHYS_BITS) maxCheck = -1; - // Fast Allocate if(Pages == 1 && MaxBits >= PHYS_BITS) { phys = MM_AllocPhys(); + if( PhysAddr ) + *PhysAddr = phys; if( !phys ) { - *PhysAddr = 0; LEAVE_RET('i', 0); } - *PhysAddr = phys; ret = MM_MapHWPages(phys, 1); if(ret == 0) { MM_DerefPhys(phys); @@ -1099,7 +1109,7 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) return 0; } LEAVE('x', ret); - return ret; + return (void*)ret; } // Slow Allocate @@ -1120,9 +1130,10 @@ tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) return 0; } - *PhysAddr = phys; + if( PhysAddr ) + *PhysAddr = phys; LEAVE('x', ret); - return ret; + return (void*)ret; } /** @@ -1134,7 +1145,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; @@ -1146,6 +1161,7 @@ void MM_UnmapHWPages(tVAddr VAddr, Uint Number) { MM_DerefPhys( gaPageTable[ i + j ] & ~0xFFF ); gaPageTable[ i + j ] = 0; + INVLPG( (tVAddr)(i+j) << 12 ); } Mutex_Release( &glTempMappings );