From 8fdfdc58b3a041f11592dd49c3a5726126b36859 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 20 Jan 2012 18:27:02 +0800 Subject: [PATCH 1/1] Kernel/x86 - Cleaning up and implmented address space nuking --- Kernel/arch/x86/include/arch.h | 2 +- Kernel/arch/x86/lib.c | 25 ++++---- Kernel/arch/x86/mm_virt.c | 110 ++++++++++++++++++++++++++------- Kernel/arch/x86/proc.c | 4 +- 4 files changed, 104 insertions(+), 37 deletions(-) diff --git a/Kernel/arch/x86/include/arch.h b/Kernel/arch/x86/include/arch.h index 9307ada3..8a987058 100644 --- a/Kernel/arch/x86/include/arch.h +++ b/Kernel/arch/x86/include/arch.h @@ -1,7 +1,7 @@ /* * Acess2 * - x86 Architecture - * arch/i386/include/arch.h + * arch/x86/include/arch.h */ #ifndef _ARCH_H_ #define _ARCH_H_ diff --git a/Kernel/arch/x86/lib.c b/Kernel/arch/x86/lib.c index a3050fe1..175f9a55 100644 --- a/Kernel/arch/x86/lib.c +++ b/Kernel/arch/x86/lib.c @@ -6,6 +6,8 @@ */ #include #include +#include +#include // GetCPUNum #define TRACE_LOCKS 0 @@ -22,8 +24,6 @@ extern tMutex glPhysAlloc; //#define TRACE_LOCK_COND (Lock != &glDebug_Lock && Lock != &glPhysAlloc.Protector) #endif -extern int GetCPUNum(void); - // === PROTOTYPES == Uint64 __divmod64(Uint64 Num, Uint64 Den, Uint64 *Rem); Uint64 __udivdi3(Uint64 Num, Uint64 Den); @@ -52,6 +52,17 @@ int CPU_HAS_LOCK(struct sShortSpinlock *Lock) return Lock->Lock == GetCPUNum() + 1; } +void __AtomicTestSetLoop(Uint *Ptr, Uint Value) +{ + __ASM__( + "1:\n\t" + "xor %%eax, %%eax;\n\t" + "lock cmpxchgl %0, (%1);\n\t" + "jnz 1b;\n\t" + :: "r"(Value), "r"(Ptr) + : "eax" // EAX clobbered + ); +} /** * \brief Acquire a Short Spinlock * \param Lock Lock pointer @@ -85,15 +96,7 @@ void SHORTLOCK(struct sShortSpinlock *Lock) __ASM__("cli"); // Wait for another CPU to release - __ASM__( - "1:\n\t" - "xor %%eax, %%eax;\n\t" - "lock cmpxchgl %0, (%1);\n\t" - "jnz 1b;\n\t" - :: "r"(cpu), "r"(&Lock->Lock) - : "eax" // EAX clobbered - ); - + __AtomicTestSetLoop( (Uint*)&Lock->Lock, cpu ); Lock->IF = IF; #if TRACE_LOCKS diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index 137240c9..6a29c564 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -16,6 +16,7 @@ #include #include #include +#include #define TAB 22 @@ -54,6 +55,15 @@ #define INVLPG(addr) __asm__ __volatile__ ("invlpg (%0)"::"r"(addr)) +#define GET_TEMP_MAPPING(cr3) do { \ + __ASM__("cli"); \ + __AtomicTestSetLoop( (Uint *)gpTmpCR3, cr3 | 3 ); \ +} while(0) +#define REL_TEMP_MAPPING() do { \ + *gpTmpCR3 = 0; \ + __ASM__("sti"); \ +} while(0) + typedef Uint32 tTabEnt; // === IMPORTS === @@ -136,6 +146,8 @@ void MM_InstallVirtual(void) for( i = ((tVAddr)&_UsertextEnd-(tVAddr)&_UsertextBase+0xFFF)/4096; i--; ) { MM_SetFlags( (tVAddr)&_UsertextBase + i*4096, 0, MM_PFLAG_KERNEL ); } + + *gpTmpCR3 = 0; } /** @@ -178,8 +190,9 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) INVLPG( Addr & ~0xFFF ); return; } - - __asm__ __volatile__ ("pushf; andw $0xFEFF, 0(%esp); popf"); + + // Disable instruction tracing + __ASM__("pushf; andw $0xFEFF, 0(%esp); popf"); Proc_GetCurThread()->bInstrTrace = 0; // If it was a user, tell the thread handler @@ -190,7 +203,7 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) (ErrorCode&16?" (Instruction Fetch)":"") ); Log_Warning("MMVirt", "Instruction %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr); - __asm__ __volatile__ ("sti"); // Restart IRQs + __ASM__("sti"); // Restart IRQs #if 1 Error_Backtrace(Regs->eip, Regs->ebp); #endif @@ -329,7 +342,7 @@ tPAddr MM_Allocate(tVAddr VAddr) { tPAddr paddr; //ENTER("xVAddr", VAddr); - //__asm__ __volatile__ ("xchg %bx,%bx"); + //__ASM__("xchg %bx,%bx"); // Check if the directory is mapped if( gaPageDir[ VAddr >> 22 ] == 0 ) { @@ -414,7 +427,7 @@ tPAddr MM_GetPhysAddr(tVAddr Addr) */ void MM_SetCR3(Uint CR3) { - __asm__ __volatile__ ("mov %0, %%cr3"::"r"(CR3)); + __ASM__("mov %0, %%cr3"::"r"(CR3)); } /** @@ -426,7 +439,7 @@ int MM_Map(tVAddr VAddr, tPAddr PAddr) //ENTER("xVAddr xPAddr", VAddr, PAddr); // Sanity check if( PAddr & 0xFFF || VAddr & 0xFFF ) { - Warning("MM_Map - Physical or Virtual Addresses are not aligned"); + Log_Warning("MM_Virt", "MM_Map - Physical or Virtual Addresses are not aligned"); //LEAVE('i', 0); return 0; } @@ -504,6 +517,58 @@ void MM_ClearUser(void) INVLPG( gaPageDir ); } +/** + * \brief Deallocate an address space + */ +void MM_ClearSpace(Uint32 CR3) +{ + int i, j; + + if(CR3 == (*gpPageCR3 & ~0xFFF)) { + Log_Error("MMVirt", "Can't clear current address space"); + return ; + } + + if( MM_GetRefCount(CR3) > 1 ) { + Log_Log("MMVirt", "CR3 %P is still referenced, not clearing", CR3); + return ; + } + + Log_Debug("MMVirt", "Clearing out address space 0x%x from 0x%x", CR3, *gpPageCR3); + + GET_TEMP_MAPPING(CR3); + INVLPG( gaTmpDir ); + + for( i = 0; i < 1024; i ++ ) + { + Uint32 *table = &gaTmpTable[i*1024]; + if( !(gaTmpDir[i] & PF_PRESENT) ) + continue ; + + INVLPG( table ); + + if( i < 768 || (i > MM_KERNEL_STACKS >> 22 && i < MM_KERNEL_STACKS_END >> 22) ) + { + for( j = 0; j < 1024; j ++ ) + { + if( !(table[j] & 1) ) + continue; + MM_DerefPhys( table[j] & ~0xFFF ); + } + } + + if( i != (PAGE_TABLE_ADDR >> 22) ) + { + MM_DerefPhys( gaTmpDir[i] & ~0xFFF ); + } + } + + + MM_DerefPhys( CR3 ); + + REL_TEMP_MAPPING(); +} + /** * \fn tPAddr MM_Clone(void) * \brief Clone the current address space @@ -511,21 +576,20 @@ void MM_ClearUser(void) tPAddr MM_Clone(void) { Uint i, j; - tVAddr ret; + tPAddr ret; Uint page = 0; tVAddr kStackBase = Proc_GetCurThread()->KernelStack - MM_KERNEL_STACK_SIZE; void *tmp; - Mutex_Acquire( &glTempFractal ); - // Create Directory Table - *gpTmpCR3 = MM_AllocPhys() | 3; - if( *gpTmpCR3 == 3 ) { - *gpTmpCR3 = 0; + ret = MM_AllocPhys(); + if( ret == 0 ) { return 0; } + + // Map + GET_TEMP_MAPPING( ret ); INVLPG( gaTmpDir ); - //LOG("Allocated Directory (%x)", *gpTmpCR3); memsetd( gaTmpDir, 0, 1024 ); if( Threads_GetPID() != 0 ) @@ -573,6 +637,10 @@ tPAddr MM_Clone(void) gaTmpDir[ PAGE_TABLE_ADDR >> 22 ] = *gpTmpCR3; continue; } + if( i == (TMP_TABLE_ADDR >> 22) ) { + gaTmpDir[ TMP_TABLE_ADDR >> 22 ] = 0; + continue ; + } if( gaPageDir[i] == 0 ) { gaTmpDir[i] = 0; @@ -628,8 +696,7 @@ tPAddr MM_Clone(void) } } - ret = *gpTmpCR3 & ~0xFFF; - Mutex_Release( &glTempFractal ); + REL_TEMP_MAPPING(); //LEAVE('x', ret); return ret; @@ -709,15 +776,10 @@ tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize) base = WORKER_STACKS + base * WORKER_STACK_SIZE; //Log(" MM_NewWorkerStack: base = 0x%x", base); - // Acquire the lock for the temp fractal mappings - Mutex_Acquire(&glTempFractal); - // Set the temp fractals to TID0's address space - *gpTmpCR3 = ((Uint)gaInitPageDir - KERNEL_BASE) | 3; - //Log(" MM_NewWorkerStack: *gpTmpCR3 = 0x%x", *gpTmpCR3); + GET_TEMP_MAPPING( ((Uint)gaInitPageDir - KERNEL_BASE) ); INVLPG( gaTmpDir ); - // 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 ]); @@ -732,9 +794,9 @@ tVAddr MM_NewWorkerStack(Uint *StackContents, size_t ContentsSize) page = MM_AllocPhys(); gaTmpTable[ (base + addr) >> 12 ] = page | 3; } - *gpTmpCR3 = 0; - // Release the temp mapping lock - Mutex_Release(&glTempFractal); + + // Release temporary fractal + REL_TEMP_MAPPING(); // NOTE: Max of 1 page // `page` is the last allocated page from the previious for loop diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 30f318f3..c804971c 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -12,6 +12,7 @@ # include #endif #include +#include // === FLAGS === #define DEBUG_TRACE_SWITCH 0 @@ -570,7 +571,7 @@ void Proc_ChangeStack(void) void Proc_ClearThread(tThread *Thread) { - Log_Warning("Proc", "TODO: Nuke address space etc"); + MM_ClearSpace(Thread->MemState.CR3); if(Thread->SavedState.SSE) { free(Thread->SavedState.SSE); Thread->SavedState.SSE = NULL; @@ -587,6 +588,7 @@ int Proc_NewKThread(void (*Fcn)(void*), void *Data) if(!newThread) return -1; // Set CR3 + MM_RefPhys( cur->MemState.CR3 ); newThread->MemState.CR3 = cur->MemState.CR3; // Create new KStack -- 2.20.1