Kernel/x86_64 - Separated task switching from timer interrupt
authorJohn Hodge <[email protected]>
Mon, 26 Sep 2011 13:22:02 +0000 (21:22 +0800)
committerJohn Hodge <[email protected]>
Mon, 26 Sep 2011 13:22:02 +0000 (21:22 +0800)
- Well, mostly (the timer still calls it, but it can be called elsewhere)

Kernel/arch/x86_64/main.c
Kernel/arch/x86_64/mm_virt.c
Kernel/arch/x86_64/proc.asm
Kernel/arch/x86_64/proc.c

index 77df362..d3b79c6 100644 (file)
@@ -25,6 +25,9 @@ char  *gsBootCmdLine = NULL;
 void kmain(Uint MbMagic, void *MbInfoPtr)
 {
        tMBoot_Info     *mbInfo;
+
+       LogF("Acess2 x86_65 v"EXPAND_STR(KERNEL_VERSION)"\n");
+       LogF(" Build %i, Git Hash %s\n", BUILD_NUM, gsGitHash);
        
        Desctab_Init();
 
index 1640586..2c91aed 100644 (file)
@@ -75,7 +75,7 @@ tMutex        glMM_TempFractalLock;
 // === CODE ===
 void MM_InitVirt(void)
 {
-       MM_DumpTables(0, -1L);
+//     MM_DumpTables(0, -1L);
 }
 
 void MM_FinishVirtualInit(void)
index 664ad21..4771e1b 100644 (file)
@@ -47,6 +47,25 @@ NewTaskHeader:
 .hlt:
        jmp .hlt
 
+[extern MM_Clone]
+[global Proc_CloneInt]
+Proc_CloneInt:
+       PUSH_GPR
+       ; Save RSP
+       mov [rdi], rsp
+       call MM_Clone
+       ; Save CR3
+       mov rsi, [rsp+0x30]
+       mov [rsi], rax
+       ; Undo the PUSH_GPR
+       add rsp, 0x80
+       mov rax, .newTask
+       ret
+.newTask:
+       POP_GPR
+       xor eax, eax
+       ret
+
 [global SaveState]
 SaveState:
        ; Save regs to RSI
@@ -69,4 +88,31 @@ SaveState:
        mov [rsp], rax  ; Restore return address
        xor eax, eax
        ret
+
+[global SwitchTasks]
+; rdi = New RSP
+; rsi = Old RSP save loc
+; rdx = New RIP
+; rcx = Old RIP save loc
+; r8 = CR3
+SwitchTasks:
+       PUSH_GPR
        
+       lea rax, [rel .restore]
+       mov QWORD [rcx], rax
+       mov [rsi], rsp
+
+       test r8, r8
+       jz .setState
+       mov cr3, r8
+       invlpg [rdi]
+       invlpg [rdi+0x1000]
+.setState:
+       mov rsp, rdi
+       jmp rdx
+
+.restore:
+       POP_GPR
+       xor eax, eax
+       ret
+
index 8cc1933..4971395 100644 (file)
@@ -37,6 +37,7 @@ extern void   APStartup(void);        // 16-bit AP startup code
 
 extern Uint    GetRIP(void);   // start.asm
 extern Uint    SaveState(Uint *RSP, Uint *Regs);
+extern Uint    Proc_CloneInt(Uint *RSP, Uint *CR3);
 extern void    NewTaskHeader(void);    // Actually takes cdecl args
 
 extern Uint64  gInitialPML4[512];      // start.asm
@@ -49,6 +50,7 @@ extern tThread        gThreadZero;
 extern void    Threads_Dump(void);
 extern void    Proc_ReturnToUser(void);
 extern void    Time_UpdateTimestamp(void);
+extern void    SwitchTasks(Uint NewSP, Uint *OldSP, Uint NewIP, Uint *OldIO, Uint CR3);
 
 // === PROTOTYPES ===
 //void ArchThreads_Init(void);
@@ -68,6 +70,7 @@ void  Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) NO
  int   Proc_Demote(Uint *Err, int Dest, tRegs *Regs);
 //void Proc_CallFaultHandler(tThread *Thread);
 //void Proc_DumpThreadCPUState(tThread *Thread);
+//void Proc_Reschedule(void);
 void   Proc_Scheduler(int CPU, Uint RSP, Uint RIP);
 
 // === GLOBALS ===
@@ -467,38 +470,35 @@ int Proc_Clone(Uint Flags)
 {
        tThread *newThread, *cur = Proc_GetCurThread();
        Uint    rip;
-       Uint    _savedregs[16+1];
-       
+
+       // Sanity check 
+       if( !(Flags & CLONE_VM) ) {
+               Log_Error("Proc", "Proc_Clone: Don't leave CLONE_VM unset, use Proc_NewKThread instead");
+               return -1;
+       }
+
+       // Create new TCB
        newThread = Threads_CloneTCB(NULL, Flags);
        if(!newThread)  return -1;
        
        // Save core machine state
-       rip = SaveState(&newThread->SavedState.RSP, &_savedregs[0]);
+       rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->MemState.CR3);
        if(rip == 0) {
                outb(0x20, 0x20);       // ACK Timer and return as child
                __asm__ __volatile__ ("sti");
                return 0;
        }
-       
-       // Initialise Memory Space (New Addr space or kernel stack)
-       if(Flags & CLONE_VM) {
-               newThread->MemState.CR3 = MM_Clone();
-               newThread->KernelStack = cur->KernelStack;
-       }
-       else {
-               Log_Error("Proc", "Proc_Clone: Don't leave CLONE_VM unset, use Proc_NewKThread instead");
-               return -1;
-       }
-       
-       Log("New (Clone) %p, rsp = %p", rip, newThread->SavedState.RSP);
+       newThread->KernelStack = cur->KernelStack;
+       newThread->SavedState.RIP = rip;
+
+       // DEBUG        
+       Log("New (Clone) %p, rsp = %p, cr3 = %p", rip, newThread->SavedState.RSP, newThread->MemState.CR3);
        {
                Uint cr3;
                __asm__ __volatile__ ("mov %%cr3, %0" : "=r" (cr3));
-               Log(" CR3 = %x, PADDR(RSP) = %x", cr3, MM_GetPhysAddr(newThread->SavedState.RSP));
+               Log("Current CR3 = 0x%x, PADDR(RSP) = 0x%x", cr3, MM_GetPhysAddr(newThread->SavedState.RSP));
        }
-       
-       // Set EIP as parent
-       newThread->SavedState.RIP = rip;
+       // /DEBUG
        
        // Lock list and add to active
        Threads_AddActive(newThread);
@@ -699,6 +699,45 @@ void Proc_DumpThreadCPUState(tThread *Thread)
        Log("  At %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
 }
 
+void Proc_Reschedule(void)
+{
+       tThread *nextthread, *curthread;
+        int    cpu = GetCPUNum();
+
+       // TODO: Wait for it?
+       if(IS_LOCKED(&glThreadListLock))        return;
+       
+       curthread = gaCPUs[cpu].Current;
+
+       nextthread = Threads_GetNextToRun(cpu, curthread);
+
+       if(nextthread == curthread)     return ;
+       if(!nextthread)
+               nextthread = gaCPUs[cpu].IdleThread;
+       if(!nextthread)
+               return ;
+
+       #if DEBUG_TRACE_SWITCH
+       LogF("\nSwitching to task %i, CR3 = 0x%x, RIP = %p, RSP = %p\n",
+               nextthread->TID,
+               nextthread->MemState.CR3,
+               nextthread->SavedState.RIP,
+               nextthread->SavedState.RSP
+               );
+       #endif
+
+       // Update CPU state
+       gaCPUs[cpu].Current = nextthread;
+       gTSSs[cpu].RSP0 = nextthread->KernelStack-4;
+
+       SwitchTasks(
+               nextthread->SavedState.RSP, &curthread->SavedState.RSP,
+               nextthread->SavedState.RIP, &curthread->SavedState.RIP,
+               nextthread->MemState.CR3
+               );
+       return ;
+}
+
 /**
  * \fn void Proc_Scheduler(int CPU)
  * \brief Swap current thread and clears dead threads
@@ -723,12 +762,6 @@ void Proc_Scheduler(int CPU, Uint RSP, Uint RIP)
                if(thread->Remaining--) return;
                // Reset quantum for next call
                thread->Remaining = thread->Quantum;
-       
-               // Save machine state
-               thread->SavedState.RSP = RSP;
-               thread->SavedState.RIP = RIP;
-               
-//             LogF("\nSaved %i, RIP = %p, rsp = %p\n", thread->TID, thread->SavedState.RIP, thread->SavedState.RSP);
                
                // TODO: Make this more stable somehow
                {
@@ -738,62 +771,9 @@ void Proc_Scheduler(int CPU, Uint RSP, Uint RIP)
                }
        }
 
-       #if BREAK_ON_SWITCH
-       {
-       tThread *oldthread = thread;
-       #endif
+       // ACK Timer here?
 
-       // Get next thread
-       thread = Threads_GetNextToRun(CPU, thread);
-       
-       // Error Check
-       if(thread == NULL) {
-               thread = gaCPUs[CPU].IdleThread;
-               //Warning("Hmm... Threads_GetNextToRun returned NULL, I don't think this should happen.\n");
-//             LogF("Zzzzz.\n");
-               //return;
-       }
-       if(thread == NULL ) {
-               return ;
-       }
-       #if BREAK_ON_SWITCH
-       if( thread != oldthread ) {
-               MAGIC_BREAK();
-       }
-       }
-       #endif
-       
-       #if DEBUG_TRACE_SWITCH
-       LogF("\nSwitching to task %i, CR3 = 0x%x, RIP = %p, RSP = %p\n",
-               thread->TID,
-               thread->MemState.CR3,
-               thread->SavedState.RIP,
-               thread->SavedState.RSP
-               );
-       #endif
-       
-       
-       if(CPU > MAX_CPUS)
-               LogF("CPU = %i", CPU);
-       // Set current thread
-       gaCPUs[CPU].Current = thread;
-       
-       // Update Kernel Stack pointer
-       gTSSs[CPU].RSP0 = thread->KernelStack-4;
-       
-       // Switch threads
-       __asm__ __volatile__ (
-               "mov %2, %%cr3\n\t"
-               "mov %0, %%rsp\n\t"     // Restore RSP
-               "invlpg (%%rsp)\n\t"
-               "invlpg 0x1000(%%rsp)\n\t"
-               "invlpg -0x1000(%%rsp)\n\t"
-               "xor %%eax, %%eax\n\t"
-               "jmp *%1" : :   // And return to where we saved state (Proc_Clone or Proc_Scheduler)
-               "r"(thread->SavedState.RSP), "r"(thread->SavedState.RIP),
-               "r"(thread->MemState.CR3)
-               );
-       for(;;);        // Shouldn't reach here
+       Proc_Reschedule();
 }
 
 // === EXPORTS ===

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