X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fmm_virt.c;h=c29db507470349e8e34cd260d59b77d28a29c17a;hb=0f48b41ce8edd3b6d549d641b35901e4b51a5132;hp=d7d1d81f948b50178e66faf479f7f8d38ccce2ff;hpb=95a7eaaa4a1065334125b65130866f8d1048ddb7;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index d7d1d81f..c29db507 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -15,7 +15,7 @@ #include #define KERNEL_STACKS 0xF0000000 -#define KERNEL_STACK_SIZE 0x00002000 +#define KERNEL_STACK_SIZE 0x00008000 #define KERNEL_STACKS_END 0xFD000000 #define WORKER_STACKS 0x00100000 // Thread0 Only! #define WORKER_STACK_SIZE KERNEL_STACK_SIZE @@ -44,15 +44,15 @@ // === IMPORTS === extern Uint32 gaInitPageDir[1024]; extern Uint32 gaInitPageTable[1024]; -extern void Threads_SegFault(Uint Addr); +extern void Threads_SegFault(tVAddr Addr); extern void Error_Backtrace(Uint eip, Uint ebp); // === PROTOTYPES === void MM_PreinitVirtual(); void MM_InstallVirtual(); -void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs); +void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs); void MM_DumpTables(tVAddr Start, tVAddr End); -tPAddr MM_DuplicatePage(Uint VAddr); +tPAddr MM_DuplicatePage(tVAddr VAddr); // === GLOBALS === tPAddr *gaPageTable = (void*)PAGE_TABLE_ADDR; @@ -63,7 +63,7 @@ tPAddr *gaTmpDir = (void*)TMP_DIR_ADDR; tPAddr *gTmpCR3 = (void*)TMP_CR3_ADDR; int gilTempMappings = 0; int gilTempFractal = 0; -Uint32 gWorkerStacks[NUM_WORKER_STACKS/32]; +Uint32 gWorkerStacks[(NUM_WORKER_STACKS+31)/32]; int giLastUsedWorker = 0; // === CODE === @@ -102,10 +102,10 @@ void MM_InstallVirtual() } /** - * \fn void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) + * \fn void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) * \brief Called on a page fault */ -void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) +void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) { //ENTER("xAddr bErrorCode", Addr, ErrorCode); @@ -248,9 +248,9 @@ void MM_DumpTables(tVAddr Start, tVAddr End) } /** - * \fn tPAddr MM_Allocate(Uint VAddr) + * \fn tPAddr MM_Allocate(tVAddr VAddr) */ -tPAddr MM_Allocate(Uint VAddr) +tPAddr MM_Allocate(tVAddr VAddr) { tPAddr paddr; // Check if the directory is mapped @@ -294,9 +294,9 @@ tPAddr MM_Allocate(Uint VAddr) } /** - * \fn void MM_Deallocate(Uint VAddr) + * \fn void MM_Deallocate(tVAddr VAddr) */ -void MM_Deallocate(Uint VAddr) +void MM_Deallocate(tVAddr VAddr) { if( gaPageDir[ VAddr >> 22 ] == 0 ) { Warning("MM_Deallocate - Directory not mapped"); @@ -315,10 +315,10 @@ void MM_Deallocate(Uint VAddr) } /** - * \fn tPAddr MM_GetPhysAddr(Uint Addr) + * \fn tPAddr MM_GetPhysAddr(tVAddr Addr) * \brief Checks if the passed address is accesable */ -tPAddr MM_GetPhysAddr(Uint Addr) +tPAddr MM_GetPhysAddr(tVAddr Addr) { if( !(gaPageDir[Addr >> 22] & 1) ) return 0; @@ -327,20 +327,36 @@ tPAddr MM_GetPhysAddr(Uint Addr) return (gaPageTable[Addr >> 12] & ~0xFFF) | (Addr & 0xFFF); } + /** - * \fn void MM_SetCR3(Uint CR3) + * \fn int MM_IsUser(tVAddr Addr) + * \brief Checks if a page is user accessable + */ +int MM_IsUser(tVAddr Addr) +{ + if( !(gaPageDir[Addr >> 22] & 1) ) + return 0; + if( !(gaPageTable[Addr >> 12] & 1) ) + return 0; + if( !(gaPageTable[Addr >> 12] & PF_USER) ) + return 0; + return 1; +} + +/** + * \fn void MM_SetCR3(tPAddr CR3) * \brief Sets the current process space */ -void MM_SetCR3(Uint CR3) +void MM_SetCR3(tPAddr CR3) { __asm__ __volatile__ ("mov %0, %%cr3"::"r"(CR3)); } /** - * \fn int MM_Map(Uint VAddr, tPAddr PAddr) + * \fn int MM_Map(tVAddr VAddr, tPAddr PAddr) * \brief Map a physical page to a virtual one */ -int MM_Map(Uint VAddr, tPAddr PAddr) +int MM_Map(tVAddr VAddr, tPAddr PAddr) { //ENTER("xVAddr xPAddr", VAddr, PAddr); // Sanity check @@ -390,10 +406,10 @@ int MM_Map(Uint VAddr, tPAddr PAddr) } /** - * \fn Uint MM_ClearUser() + * \fn tVAddr MM_ClearUser() * \brief Clear user's address space */ -Uint MM_ClearUser() +tVAddr MM_ClearUser() { Uint i, j; @@ -424,15 +440,15 @@ Uint MM_ClearUser() } /** - * \fn Uint MM_Clone() + * \fn tPAddr MM_Clone() * \brief Clone the current address space */ -Uint MM_Clone() +tPAddr MM_Clone() { Uint i, j; - Uint ret; + tVAddr ret; Uint page = 0; - Uint kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE; + tVAddr kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE; void *tmp; LOCK( &gilTempFractal ); @@ -550,12 +566,12 @@ Uint MM_Clone() } /** - * \fn Uint MM_NewKStack() + * \fn tVAddr MM_NewKStack() * \brief Create a new kernel stack */ -Uint MM_NewKStack() +tVAddr MM_NewKStack() { - Uint base = KERNEL_STACKS; + tVAddr base = KERNEL_STACKS; Uint i; for(;base= NUM_WORKER_STACKS) { Warning("Uh-oh! Out of worker stacks"); @@ -611,19 +628,23 @@ Uint MM_NewWorkerStack() giLastUsedWorker = base; // We have one base = WORKER_STACKS + base * WORKER_STACK_SIZE; + //Log(" MM_NewWorkerStack: base = 0x%x", base); // Acquire the lock for the temp fractal mappings LOCK(&gilTempFractal); // Set the temp fractals to TID0's address space - *gTmpCR3 = (Uint)gaInitPageDir | 3; + *gTmpCR3 = ((Uint)gaInitPageDir - KERNEL_BASE) | 3; + //Log(" MM_NewWorkerStack: *gTmpCR3 = 0x%x", *gTmpCR3); INVLPG( gaTmpDir ); + // Check if the directory is mapped (we are assuming that the stacks - // will fit neatly in a directory + // will fit neatly in a directory) + //Log(" MM_NewWorkerStack: gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]); if(gaTmpDir[ base >> 22 ] == 0) { gaTmpDir[ base >> 22 ] = MM_AllocPhys() | 3; - INVLPG( &gaTmpTable[ (base>>22) & ~0x3FF ] ); + INVLPG( &gaTmpTable[ (base>>12) & ~0x3FF ] ); } // Mapping Time! @@ -632,6 +653,7 @@ Uint MM_NewWorkerStack() pages[ addr >> 12 ] = MM_AllocPhys(); gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3; } + *gTmpCR3 = 0; // Release the temp mapping lock RELEASE(&gilTempFractal); @@ -639,6 +661,9 @@ Uint MM_NewWorkerStack() oldstack = (esp + KERNEL_STACK_SIZE-1) & ~(KERNEL_STACK_SIZE-1); esp = oldstack - esp; // ESP as an offset in the stack + // Make `base` be the top of the stack + base += WORKER_STACK_SIZE; + i = (WORKER_STACK_SIZE>>12) - 1; // Copy the contents of the old stack to the new one, altering the addresses // `addr` is refering to bytes from the stack base (mem downwards) @@ -655,18 +680,19 @@ Uint MM_NewWorkerStack() else // Seems not, best leave it alone tmpPage[j] = stack[j]; } - MM_FreeTemp((Uint)tmpPage); + MM_FreeTemp((tVAddr)tmpPage); i --; } + //Log("MM_NewWorkerStack: RETURN 0x%x", base); return base; } /** - * \fn void MM_SetFlags(Uint VAddr, Uint Flags, Uint Mask) + * \fn void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask) * \brief Sets the flags on a page */ -void MM_SetFlags(Uint VAddr, Uint Flags, Uint Mask) +void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask) { tPAddr *ent; if( !(gaPageDir[VAddr >> 22] & 1) ) return ; @@ -703,10 +729,10 @@ void MM_SetFlags(Uint VAddr, Uint Flags, Uint Mask) } /** - * \fn tPAddr MM_DuplicatePage(Uint VAddr) + * \fn tPAddr MM_DuplicatePage(tVAddr VAddr) * \brief Duplicates a virtual page to a physical one */ -tPAddr MM_DuplicatePage(Uint VAddr) +tPAddr MM_DuplicatePage(tVAddr VAddr) { tPAddr ret; Uint temp; @@ -744,7 +770,7 @@ tPAddr MM_DuplicatePage(Uint VAddr) * \brief Create a temporary memory mapping * \todo Show Luigi Barone (C Lecturer) and see what he thinks */ -Uint MM_MapTemp(tPAddr PAddr) +tVAddr MM_MapTemp(tPAddr PAddr) { int i; @@ -775,10 +801,10 @@ Uint MM_MapTemp(tPAddr PAddr) } /** - * \fn void MM_FreeTemp(Uint PAddr) + * \fn void MM_FreeTemp(tVAddr PAddr) * \brief Free's a temp mapping */ -void MM_FreeTemp(Uint VAddr) +void MM_FreeTemp(tVAddr VAddr) { int i = VAddr >> 12; //ENTER("xVAddr", VAddr); @@ -790,10 +816,10 @@ void MM_FreeTemp(Uint VAddr) } /** - * \fn Uint MM_MapHWPage(tPAddr PAddr, Uint Number) + * \fn tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number) * \brief Allocates a contigous number of pages */ -Uint MM_MapHWPage(tPAddr PAddr, Uint Number) +tVAddr MM_MapHWPage(tPAddr PAddr, Uint Number) { int i, j; @@ -828,10 +854,82 @@ Uint MM_MapHWPage(tPAddr PAddr, Uint Number) } /** - * \fn void MM_UnmapHWPage(Uint VAddr, Uint Number) + * \fn tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) + * \brief Allocates DMA physical memory + * \param Pages Number of pages required + * \param MaxBits Maximum number of bits the physical address can have + * \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) +{ + tPAddr maxCheck = (1 << MaxBits); + tPAddr phys; + tVAddr ret; + + ENTER("iPages iMaxBits pPhysAddr", Pages, MaxBits, PhysAddr); + + // Sanity Check + if(MaxBits < 12 || !PhysAddr) { + LEAVE('i', 0); + return 0; + } + + // Bound + if(MaxBits >= PHYS_BITS) maxCheck = -1; + + // Fast Allocate + if(Pages == 1 && MaxBits >= PHYS_BITS) + { + phys = MM_AllocPhys(); + *PhysAddr = phys; + ret = MM_MapHWPage(phys, 1); + if(ret == 0) { + MM_DerefPhys(phys); + LEAVE('i', 0); + return 0; + } + LEAVE('x', ret); + return ret; + } + + // Slow Allocate + phys = MM_AllocPhysRange(Pages); + // - Was it allocated? + if(phys == 0) { + LEAVE('i', 0); + return 0; + } + // - Check if the memory is OK + if(phys + (Pages-1)*0x1000 > maxCheck) + { + // Deallocate and return 0 + for(;Pages--;phys+=0x1000) + MM_DerefPhys(phys); + LEAVE('i', 0); + return 0; + } + + // Allocated successfully, now map + ret = MM_MapHWPage(phys, Pages); + if( ret == 0 ) { + // If it didn't map, free then return 0 + for(;Pages--;phys+=0x1000) + MM_DerefPhys(phys); + LEAVE('i', 0); + return 0; + } + + *PhysAddr = phys; + LEAVE('x', ret); + return ret; +} + +/** + * \fn void MM_UnmapHWPage(tVAddr VAddr, Uint Number) * \brief Unmap a hardware page */ -void MM_UnmapHWPage(Uint VAddr, Uint Number) +void MM_UnmapHWPage(tVAddr VAddr, Uint Number) { int i, j; // Sanity Check @@ -855,4 +953,5 @@ EXPORT(MM_GetPhysAddr); EXPORT(MM_Map); //EXPORT(MM_Unmap); EXPORT(MM_MapHWPage); +EXPORT(MM_AllocDMA); EXPORT(MM_UnmapHWPage);