Multiple IPStack Related changes (and other bugfixes)
[tpg/acess2.git] / Kernel / arch / x86 / proc.c
index 94de734..ad83c99 100644 (file)
 
 // === FLAGS ===
 #define DEBUG_TRACE_SWITCH     0
+#define DEBUG_DISABLE_DOUBLEFAULT      1
 
 // === CONSTANTS ===
-#define        SWITCH_MAGIC    0xFFFACE55      // There is no code in this area
+#define        SWITCH_MAGIC    0xFF5317C8      // FF SWITCH - There is no code in this area
 // Base is 1193182
 #define TIMER_BASE      1193182
-#define TIMER_DIVISOR   11931  //~100Hz
+#define TIMER_DIVISOR   11932  //~100Hz
 
 // === TYPES ===
 #if USE_MP
@@ -41,20 +42,14 @@ extern void APStartup(void);        // 16-bit AP startup code
 extern Uint    GetEIP(void);   // start.asm
 extern int     GetCPUNum(void);        // start.asm
 extern Uint32  gaInitPageDir[1024];    // start.asm
-extern void    Kernel_Stack_Top;
-extern tSpinlock       glThreadListLock;
+extern char    Kernel_Stack_Top[];
+extern tShortSpinlock  glThreadListLock;
 extern int     giNumCPUs;
 extern int     giNextTID;
-extern int     giTotalTickets;
-extern int     giNumActiveThreads;
 extern tThread gThreadZero;
-extern tThread *gActiveThreads;
-extern tThread *gSleepingThreads;
-extern tThread *gDeleteThreads;
-extern void    Threads_Dump(void);
 extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags);
 extern void    Isr8(void);     // Double Fault
-extern void    Proc_ReturnToUser(void);
+extern void    Proc_ReturnToUser(tVAddr Handler, Uint Argument);
 
 // === PROTOTYPES ===
 void   ArchThreads_Init(void);
@@ -292,7 +287,7 @@ void ArchThreads_Init(void)
        MM_FinishVirtualInit();
        #endif
        
-       #if 0
+       #if !DEBUG_DISABLE_DOUBLEFAULT
        // Initialise Double Fault TSS
        gGDT[5].BaseLow = (Uint)&gDoubleFault_TSS & 0xFFFF;
        gGDT[5].BaseMid = (Uint)&gDoubleFault_TSS >> 16;
@@ -310,6 +305,11 @@ void ArchThreads_Init(void)
        outb(0x40, TIMER_DIVISOR&0xFF); // Low Byte of Divisor
        outb(0x40, (TIMER_DIVISOR>>8)&0xFF);    // High Byte
        
+       Log("Timer Frequency %i.%03i Hz",
+               TIMER_BASE/TIMER_DIVISOR,
+               ((Uint64)TIMER_BASE*1000/TIMER_DIVISOR)%1000
+               );
+       
        #if USE_MP
        // Get the count setting for APIC timer
        Log("Determining APIC Count");
@@ -340,7 +340,7 @@ void ArchThreads_Init(void)
                gTSSs[pos].SS0 = 0x10;
                gTSSs[pos].ESP0 = 0;    // Set properly by scheduler
                gGDT[6+pos].BaseLow = ((Uint)(&gTSSs[pos])) & 0xFFFF;
-               gGDT[6+pos].BaseMid = ((Uint)(&gTSSs[pos])) >> 16;
+               gGDT[6+pos].BaseMid = ((Uint)(&gTSSs[pos]) >> 16) & 0xFFFF;
                gGDT[6+pos].BaseHi = ((Uint)(&gTSSs[pos])) >> 24;
        #if USE_MP
        }
@@ -348,6 +348,9 @@ void ArchThreads_Init(void)
        
        // Load the BSP's TSS
        __asm__ __volatile__ ("ltr %%ax"::"a"(0x30));
+       // Set Current Thread and CPU Number in DR0 and DR1
+       __asm__ __volatile__ ("mov %0, %%db0"::"r"(&gThreadZero));
+       __asm__ __volatile__ ("mov %0, %%db1"::"r"(0));
        
        #if USE_MP
        gaCPUs[0].Current = &gThreadZero;
@@ -379,7 +382,7 @@ void MP_StartAP(int CPU)
        // Set location of AP startup code and mark for a warm restart
        *(Uint16*)(KERNEL_BASE|0x467) = (Uint)&APWait - (KERNEL_BASE|0xFFFF0);
        *(Uint16*)(KERNEL_BASE|0x469) = 0xFFFF;
-       outb(0x70, 0x0F);       outb(0x71, 0x0A);       // Warm Reset
+       outb(0x70, 0x0F);       outb(0x71, 0x0A);       // Set warm reset flag
        MP_SendIPI(gaCPUs[CPU].APICID, 0, 5);   // Init IPI
        
        // Delay
@@ -433,16 +436,19 @@ void Proc_Start(void)
        // Start APs
        for( i = 0; i < giNumCPUs; i ++ )
        {
+                int    tid;
+               if(i)   gaCPUs[i].Current = NULL;
+               
                // Create Idle Task
-               if(Proc_Clone(0, 0) == 0)
+               if( (tid = Proc_Clone(0, 0)) == 0)
                {
-                       gaCPUs[i].IdleThread = Proc_GetCurThread();
-                       gaCPUs[i].IdleThread->ThreadName = "Idle Thread";
-                       gaCPUs[i].IdleThread->NumTickets = 0;   // Never called randomly
-                       gaCPUs[i].IdleThread->Quantum = 1;      // 1 slice quantum
                        for(;;) HALT(); // Just yeilds
                }
-               gaCPUs[i].Current = NULL;
+               gaCPUs[i].IdleThread = Threads_GetThread(tid);
+               gaCPUs[i].IdleThread->ThreadName = "Idle Thread";
+               Threads_SetPriority( gaCPUs[i].IdleThread, -1 );        // Never called randomly
+               gaCPUs[i].IdleThread->Quantum = 1;      // 1 slice quantum
+               
                
                // Start the AP
                if( i != giProc_BootProcessorID ) {
@@ -457,14 +463,13 @@ void Proc_Start(void)
        Log("Waiting for APs to come up\n");
        __asm__ __volatile__ ("sti");
        while( giNumInitingCPUs )       __asm__ __volatile__ ("hlt");
-       MM_FinishVirtualInit();
        #else
        // Create Idle Task
        if(Proc_Clone(0, 0) == 0)
        {
                gpIdleThread = Proc_GetCurThread();
                gpIdleThread->ThreadName = "Idle Thread";
-               gpIdleThread->NumTickets = 0;   // Never called randomly
+               Threads_SetPriority( gpIdleThread, -1 );        // Never called randomly
                gpIdleThread->Quantum = 1;      // 1 slice quantum
                for(;;) HALT(); // Just yeilds
        }
@@ -475,6 +480,7 @@ void Proc_Start(void)
        // Start Interrupts (and hence scheduler)
        __asm__ __volatile__("sti");
        #endif
+       MM_FinishVirtualInit();
 }
 
 /**
@@ -484,7 +490,6 @@ void Proc_Start(void)
 tThread *Proc_GetCurThread(void)
 {
        #if USE_MP
-       //return gaCPUs[ gaAPIC_to_CPU[gpMP_LocalAPIC->ID.Val&0xFF] ].Current;
        return gaCPUs[ GetCPUNum() ].Current;
        #else
        return gCurrentThread;
@@ -566,7 +571,11 @@ int Proc_Clone(Uint *Err, Uint Flags)
                Uint    tmpEbp, oldEsp = esp;
 
                // Set CR3
+               #if USE_PAE
+               # warning "PAE Unimplemented"
+               #else
                newThread->MemState.CR3 = cur->MemState.CR3;
+               #endif
 
                // Create new KStack
                newThread->KernelStack = MM_NewKStack();
@@ -599,7 +608,14 @@ int Proc_Clone(Uint *Err, Uint Flags)
        newThread->SavedState.EBP = ebp;
        eip = GetEIP();
        if(eip == SWITCH_MAGIC) {
-               outb(0x20, 0x20);       // ACK Timer and return as child
+               __asm__ __volatile__ ("mov %0, %%db0" : : "r" (newThread) );
+               #if USE_MP
+               // ACK the interrupt
+               if( GetCPUNum() )
+                       gpMP_LocalAPIC->EOI.Val = 0;
+               else
+               #endif
+                       outb(0x20, 0x20);       // ACK Timer and return as child
                __asm__ __volatile__ ("sti");   // Restart interrupts
                return 0;
        }
@@ -634,7 +650,7 @@ int Proc_SpawnWorker(void)
        // Set Thread ID
        new->TID = giNextTID++;
        // Create a new worker stack (in PID0's address space)
-       // The stack is relocated by this code
+       // - The stack is relocated by this function
        new->KernelStack = MM_NewWorkerStack();
 
        // Get ESP and EBP based in the new stack
@@ -648,14 +664,21 @@ int Proc_SpawnWorker(void)
        new->SavedState.EBP = ebp;
        eip = GetEIP();
        if(eip == SWITCH_MAGIC) {
-               outb(0x20, 0x20);       // ACK Timer and return as child
+               __asm__ __volatile__ ("mov %0, %%db0" : : "r"(new));
+               #if USE_MP
+               // ACK the interrupt
+               if(GetCPUNum())
+                       gpMP_LocalAPIC->EOI.Val = 0;
+               else
+               #endif
+                       outb(0x20, 0x20);       // ACK Timer and return as child
+               __asm__ __volatile__ ("sti");   // Restart interrupts
                return 0;
        }
        
        // Set EIP as parent
        new->SavedState.EIP = eip;
        // Mark as active
-       new->Status = THREAD_STAT_ACTIVE;
        Threads_AddActive( new );
        
        return new->TID;
@@ -810,7 +833,7 @@ void Proc_CallFaultHandler(tThread *Thread)
 {
        // Rewinds the stack and calls the user function
        // Never returns
-       __asm__ __volatile__ ("mov %0, %%ebp;\n\tcall Proc_ReturnToUser" :: "r"(Thread->FaultHandler));
+       Proc_ReturnToUser( Thread->FaultHandler, Thread->CurFaultNum );
        for(;;);
 }
 
@@ -826,32 +849,6 @@ void Proc_Scheduler(int CPU)
        // If the spinlock is set, let it complete
        if(IS_LOCKED(&glThreadListLock))        return;
        
-       // Clear Delete Queue
-       while(gDeleteThreads)
-       {
-               thread = gDeleteThreads->Next;
-               if(gDeleteThreads->IsLocked) {  // Only free if structure is unused
-                       gDeleteThreads->Status = THREAD_STAT_NULL;
-                       free( gDeleteThreads );
-               }
-               gDeleteThreads = thread;
-       }
-       
-       // Check if there is any tasks running
-       if(giNumActiveThreads == 0) {
-               #if 0
-               Log("No Active threads, sleeping");
-               #endif
-               #if USE_MP
-               if(CPU)
-                       gpMP_LocalAPIC->EOI.Val = 0;
-               else
-               #endif
-                       outb(0x20, 0x20);
-               __asm__ __volatile__ ("hlt");
-               return;
-       }
-       
        // Get current thread
        #if USE_MP
        thread = gaCPUs[CPU].Current;
@@ -862,13 +859,14 @@ void Proc_Scheduler(int CPU)
        if( thread )
        {
                // Reduce remaining quantum and continue timeslice if non-zero
-               if(thread->Remaining--) return;
+               if( thread->Remaining-- )
+                       return;
                // Reset quantum for next call
                thread->Remaining = thread->Quantum;
                
                // Get machine state
-               __asm__ __volatile__ ("mov %%esp, %0":"=r"(esp));
-               __asm__ __volatile__ ("mov %%ebp, %0":"=r"(ebp));
+               __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
                
@@ -881,17 +879,23 @@ void Proc_Scheduler(int CPU)
        // Get next thread to run
        thread = Threads_GetNextToRun(CPU, thread);
        
-       // No avaliable tasks, just go into low power mode
+       // No avaliable tasks, just go into low power mode (idle thread)
        if(thread == NULL) {
-               //HALT();
-               //return;
                #if USE_MP
                thread = gaCPUs[CPU].IdleThread;
+               Log("CPU %i Running Idle Thread", CPU);
                #else
                thread = gpIdleThread;
                #endif
        }
        
+       // Set current thread
+       #if USE_MP
+       gaCPUs[CPU].Current = thread;
+       #else
+       gCurrentThread = thread;
+       #endif
+       
        #if DEBUG_TRACE_SWITCH
        Log("Switching to task %i, CR3 = 0x%x, EIP = %p",
                thread->TID,
@@ -900,15 +904,10 @@ void Proc_Scheduler(int CPU)
                );
        #endif
        
-       // Set current thread
-       #if USE_MP
-       gaCPUs[CPU].Current = thread;
-       #else
-       gCurrentThread = thread;
+       #if USE_MP      // MP Debug
+       Log("CPU = %i, Thread %p", CPU, thread);
        #endif
        
-       //Log("CPU = %i", CPU);
-       
        // Update Kernel Stack pointer
        gTSSs[CPU].ESP0 = thread->KernelStack-4;
        
@@ -916,7 +915,7 @@ void Proc_Scheduler(int CPU)
        #if USE_PAE
        # error "Todo: Implement PAE Address space switching"
        #else
-               __asm__ __volatile__ ("mov %0, %%cr3"::"a"(thread->MemState.CR3));
+       __asm__ __volatile__ ("mov %0, %%cr3" : : "a" (thread->MemState.CR3));
        #endif
        
        #if 0

UCC git Repository :: git.ucc.asn.au