From 95d6bcfbf5ff9d9921ca70997a64f2580d1f91a7 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 28 Aug 2011 12:01:32 +0800 Subject: [PATCH] Kernel/x86 - Misc fixes - Fixed bugs in PMM > Reference counts were not being filled correctly > Nodes were not stored correctly - Added some improved output to debug / MM_DumpTables - Fixed VM8086 sometimes hard locking - Improved bInstrTrace support --- Kernel/arch/x86/desctab.asm | 8 +++++++- Kernel/arch/x86/errors.c | 9 +++++++++ Kernel/arch/x86/mm_phys.c | 37 ++++++++++++++++++++++++------------- Kernel/arch/x86/mm_virt.c | 17 +++++++++-------- Kernel/arch/x86/proc.c | 25 +++++++++++++++++++------ Kernel/arch/x86/vm8086.c | 17 ++++++++--------- 6 files changed, 76 insertions(+), 37 deletions(-) diff --git a/Kernel/arch/x86/desctab.asm b/Kernel/arch/x86/desctab.asm index dc064f57..ab7f8c2f 100644 --- a/Kernel/arch/x86/desctab.asm +++ b/Kernel/arch/x86/desctab.asm @@ -249,12 +249,18 @@ Isr240.jmp: [extern ErrorHandler] ErrorCommon: ;xchg bx, bx ; MAGIC BREAK + pusha push ds push es push fs push gs - + + ; Clear TF +; pushf +; and WORD [esp], 0xFEFF +; popf + mov ax, 0x10 mov ds, ax mov es, ax diff --git a/Kernel/arch/x86/errors.c b/Kernel/arch/x86/errors.c index 3821281d..15fe22b0 100644 --- a/Kernel/arch/x86/errors.c +++ b/Kernel/arch/x86/errors.c @@ -20,6 +20,7 @@ extern void MM_DumpTables(tVAddr, tVAddr); // === PROTOTYPES === void __stack_chk_fail(void); void ErrorHandler(tRegs *Regs); +void Proc_PrintBacktrace(void); void Error_Backtrace(Uint eip, Uint ebp); void StartupPrint(char *Str); @@ -160,6 +161,14 @@ void ErrorHandler(tRegs *Regs) for(;;) __asm__ __volatile__ ("hlt"); } + +void Proc_PrintBacktrace(void) +{ + Uint32 ebp; + __asm__ __volatile__ ("mov %%ebp, %0" : "=r" (ebp)); + Error_Backtrace( *(Uint32*)(ebp+4), *(Uint32*)ebp ); +} + /** * \fn void Error_Backtrace(Uint eip, Uint ebp) * \brief Unrolls the stack to trace execution diff --git a/Kernel/arch/x86/mm_phys.c b/Kernel/arch/x86/mm_phys.c index b84ceb6b..cd4187e5 100644 --- a/Kernel/arch/x86/mm_phys.c +++ b/Kernel/arch/x86/mm_phys.c @@ -13,6 +13,7 @@ // === IMPORTS === extern void gKernelEnd; +extern void Proc_PrintBacktrace(void); // === PROTOTYPES === void MM_Install(tMBoot_Info *MBoot); @@ -256,7 +257,10 @@ tPAddr MM_AllocPhys(void) LEAVE('X', ret); #if TRACE_ALLOCS - Log_Debug("PMem", "MM_AllocPhys: RETURN 0x%llx (%i free)", ret, giPageCount-giPhysAlloc); + if( now() > 4000 ) { + Log_Debug("PMem", "MM_AllocPhys: RETURN %P (%i free)", ret, giPageCount-giPhysAlloc); + Proc_PrintBacktrace(); + } #endif return ret; } @@ -412,7 +416,9 @@ void MM_RefPhys(tPAddr PAddr) // Reference the page if( gaPageReferences ) { - if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) == 0 ) { + if( MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) == 0 ) + { + int i, base; tVAddr addr = ((tVAddr)&gaPageReferences[PAddr]) & ~0xFFF; Log_Debug("PMem", "MM_RefPhys: Allocating info for %X", PAddr); Mutex_Release( &glPhysAlloc ); @@ -420,7 +426,11 @@ void MM_RefPhys(tPAddr PAddr) Log_KernelPanic("PMem", "MM_RefPhys: Out of physical memory"); } Mutex_Acquire( &glPhysAlloc ); - memset( (void*)addr, 0, 0x1000 ); + + base = PAddr & ~(1024-1); + for( i = 0; i < 1024; i ++ ) { + gaPageReferences[base + i] = (gaPageBitmap[(base+i)/32] & (1 << (base+i)%32)) ? 1 : 0; + } } gaPageReferences[ PAddr ] ++; } @@ -464,21 +474,22 @@ void MM_DerefPhys(tPAddr PAddr) if( !MM_GetPhysAddr( (tVAddr)&gaPageReferences[PAddr] ) || (-- gaPageReferences[PAddr]) == 0 ) { #if TRACE_ALLOCS - Log_Debug("PMem", "MM_DerefPhys: Free'd 0x%x (%i free)", PAddr, giPageCount-giPhysAlloc); + Log_Debug("PMem", "MM_DerefPhys: Free'd %P (%i free)", PAddr<<12, giPageCount-giPhysAlloc); + Proc_PrintBacktrace(); #endif //LOG("Freed 0x%x by %p\n", PAddr<<12, __builtin_return_address(0)); giPhysAlloc --; gaPageBitmap[ PAddr / 32 ] &= ~(1 << (PAddr&31)); if(gaPageBitmap[ PAddr / 32 ] == 0) gaSuperBitmap[ PAddr >> 10 ] &= ~(1 << ((PAddr >> 5)&31)); - } - if( MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) ) - { - gaPageNodes[PAddr] = NULL; - // TODO: Free Node Page when fully unused + if( MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) ) + { + gaPageNodes[PAddr] = NULL; + // TODO: Free Node Page when fully unused + } } - + // Release spinlock Mutex_Release( &glPhysAlloc ); } @@ -522,14 +533,14 @@ int MM_SetPageNode(tPAddr PAddr, void *Node) } gaPageNodes[PAddr] = Node; +// Log("gaPageNodes[0x%x] = %p", PAddr, Node); return 0; } int MM_GetPageNode(tPAddr PAddr, void **Node) { - if( MM_GetRefCount(PAddr) == 0 ) { - return 1; - } + if( MM_GetRefCount(PAddr) == 0 ) return 1; + PAddr /= PAGE_SIZE; if( !MM_GetPhysAddr( (tVAddr) &gaPageNodes[PAddr] ) ) { *Node = NULL; diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index b2f11c38..77ee4f6f 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -175,21 +175,23 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) gaPageTable[Addr>>12] |= paddr|PF_PRESENT|PF_WRITE; } - Log_Debug("MMVirt", "COW for %p", Addr); + Log_Debug("MMVirt", "COW for %p (%P)", Addr, gaPageTable[Addr>>12]); INVLPG( Addr & ~0xFFF ); return; } + __asm__ __volatile__ ("pushf; andw $0xFEFF, 0(%esp); popf"); + Proc_GetCurThread()->bInstrTrace = 0; + // If it was a user, tell the thread handler if(ErrorCode & 4) { - Log_Warning("MMVirt", "%s %s %s memory%s", - (ErrorCode&4?"User":"Kernel"), + Log_Warning("MMVirt", "User %s %s memory%s", (ErrorCode&2?"write to":"read from"), (ErrorCode&1?"bad/locked":"non-present"), (ErrorCode&16?" (Instruction Fetch)":"") ); - Warning("User Pagefault: Instruction at %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr); + Log_Warning("MMVirt", "Instruction %04x:%08x accessed %p", Regs->cs, Regs->eip, Addr); __asm__ __volatile__ ("sti"); // Restart IRQs #if 1 Error_Backtrace(Regs->eip, Regs->ebp); @@ -205,8 +207,7 @@ void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) Warning("Reserved Bits Trashed!"); else { - Warning("%s %s %s memory%s", - (ErrorCode&4?"User":"Kernel"), + Warning("Kernel %s %s memory%s", (ErrorCode&2?"write to":"read from"), (ErrorCode&1?"bad/locked":"non-present"), (ErrorCode&16?" (Instruction Fetch)":"") @@ -278,7 +279,7 @@ void MM_DumpTables(tVAddr Start, tVAddr End) if( !(gaPageDir[curPos>>22] & PF_PRESENT) || !(gaPageTable[page] & PF_PRESENT) || (gaPageTable[page] & MASK) != expected - || (tmpnode=NULL,MM_GetPageNode(curPos, &tmpnode), tmpnode != expected_node)) + || (tmpnode=NULL,MM_GetPageNode(expected, &tmpnode), tmpnode != expected_node)) { if(expected) { tPAddr orig = gaPageTable[rangeStart>>12]; @@ -299,7 +300,7 @@ void MM_DumpTables(tVAddr Start, tVAddr End) if( !(gaPageTable[curPos>>12] & PF_PRESENT) ) continue; expected = (gaPageTable[page] & MASK); - MM_GetPageNode(curPos, &expected_node); + MM_GetPageNode(expected, &expected_node); rangeStart = curPos; } if(expected) expected += 0x1000; diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 8cff256f..8598fa65 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -950,10 +950,6 @@ void Proc_Scheduler(int CPU) thread = gCurrentThread; #endif - // NOTE: - // 2011-04-05 - // Bug may be caused by DR0 not being maintained somewhere, hence - // login is getting loaded with the idle state. if( thread ) { tRegs *regs; @@ -967,7 +963,24 @@ void Proc_Scheduler(int CPU) __asm__ __volatile__ ( "mov %%esp, %0" : "=r" (esp) ); __asm__ __volatile__ ( "mov %%ebp, %0" : "=r" (ebp) ); eip = GetEIP(); - if(eip == SWITCH_MAGIC) return; // Check if a switch happened + if(eip == SWITCH_MAGIC) { + __asm__ __volatile__ ( "nop" : : : "eax","ebx","ecx","edx","edi","esi"); + regs = (tRegs*)(ebp+(2+2)*4); // EBP,Ret + CPU,CurThread + #if USE_MP + thread = gaCPUs[CPU].Current; + #else + thread = gCurrentThread; + #endif + if(thread->bInstrTrace) { + regs->eflags |= 0x100; // Set TF +// LogF("Tracing enabled\n"); + Log("%p Scheduled (EIP = %p)", thread, thread->SavedState.EIP); + } + else + regs->eflags &= ~0x100; + + return; // Check if a switch happened + } // Save machine state thread->SavedState.ESP = esp; @@ -1034,7 +1047,7 @@ void Proc_Scheduler(int CPU) #endif if( thread->bInstrTrace ) { - Log("%p Scheduled", thread); + Log("%p Scheduled (EIP = %p)", thread, thread->SavedState.EIP); } // Set thread pointer diff --git a/Kernel/arch/x86/vm8086.c b/Kernel/arch/x86/vm8086.c index 46daeefd..589d9a73 100644 --- a/Kernel/arch/x86/vm8086.c +++ b/Kernel/arch/x86/vm8086.c @@ -7,6 +7,7 @@ #include #include #include +#include // === CONSTANTS === #define VM8086_MAGIC_CS 0xFFFF @@ -47,6 +48,8 @@ void VM8086_GPF(tRegs *Regs); // === GLOBALS === MODULE_DEFINE(0, 0x100, VM8086, VM8086_Install, NULL, NULL); tMutex glVM8086_Process; +tSemaphore gVM8086_TaskComplete; +tSemaphore gVM8086_TasksToDo; tPID gVM8086_WorkerPID; tTID gVM8086_CallingThread; tVM8086 volatile * volatile gpVM8086_State = (void*)-1; // Set to -1 to avoid race conditions @@ -181,16 +184,12 @@ void VM8086_GPF(tRegs *Regs) gpVM8086_State->DS = Regs->ds; gpVM8086_State->ES = Regs->es; gpVM8086_State = NULL; // Wake the caller - Threads_WakeTID(gVM8086_CallingThread); + Semaphore_Signal(&gVM8086_TaskComplete, 1); } //Log_Log("VM8086", "Waiting for something to do"); __asm__ __volatile__ ("sti"); - // Wait for a new task - while(!gpVM8086_State) { - Threads_Sleep(); - //Log_Log("VM8086", "gpVM8086_State = %p", gpVM8086_State); - } + Semaphore_Wait(&gVM8086_TasksToDo, 1); //Log_Log("VM8086", "We have a task (%p)", gpVM8086_State); Regs->esp -= 2; *(Uint16*volatile)( (Regs->ss<<4) + (Regs->esp&0xFFFF) ) = VM8086_MAGIC_CS; @@ -428,9 +427,9 @@ void VM8086_Int(tVM8086 *State, Uint8 Interrupt) gpVM8086_State = State; gVM8086_CallingThread = Threads_GetTID(); - Threads_WakeTID( gVM8086_WorkerPID ); - Threads_Sleep(); - while( gpVM8086_State != NULL ) Threads_Sleep(); + Semaphore_Signal(&gVM8086_TasksToDo, 1); + + Semaphore_Wait(&gVM8086_TaskComplete, 1); Mutex_Release( &glVM8086_Process ); } -- 2.20.1