[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
// === 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);
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
// === IMPORTS ===
extern void gKernelEnd;
+extern void Proc_PrintBacktrace(void);
// === PROTOTYPES ===
void MM_Install(tMBoot_Info *MBoot);
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;
}
// 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 );
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 ] ++;
}
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 );
}
}
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;
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);
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)":"")
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];
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;
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;
__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;
#endif
if( thread->bInstrTrace ) {
- Log("%p Scheduled", thread);
+ Log("%p Scheduled (EIP = %p)", thread, thread->SavedState.EIP);
}
// Set thread pointer
#include <vm8086.h>
#include <modules.h>
#include <hal_proc.h>
+#include <semaphore.h>
// === CONSTANTS ===
#define VM8086_MAGIC_CS 0xFFFF
// === 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
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;
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 );
}