X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86_64%2Fproc.c;h=497139597358677adb2655289601a3d2c6c61250;hb=6e41a8a3aa767cd5aeddbad393ce4f637a47a367;hp=e83c20a9f43c96a0c167d3666ed5429b0884694d;hpb=d1d3bfa26bd78e298ad2431c4f86e2ea94515aab;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86_64/proc.c b/Kernel/arch/x86_64/proc.c index e83c20a9..49713959 100644 --- a/Kernel/arch/x86_64/proc.c +++ b/Kernel/arch/x86_64/proc.c @@ -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,33 +470,35 @@ int Proc_Clone(Uint Flags) { tThread *newThread, *cur = Proc_GetCurThread(); Uint rip; - Uint _savedregs[16]; - + + // 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\n", rip, newThread->SavedState.RSP); - - // Set EIP as parent + 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("Current CR3 = 0x%x, PADDR(RSP) = 0x%x", cr3, MM_GetPhysAddr(newThread->SavedState.RSP)); + } + // /DEBUG // Lock list and add to active Threads_AddActive(newThread); @@ -603,7 +608,8 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char ** for( i = 0; EnvP[i]; i++ ) EnvP[i] += delta; // User Mode Segments - ss = 0x23; cs = 0x1B; + // 0x2B = 64-bit + ss = 0x23; cs = 0x2B; // Arguments *--stack = (Uint)EnvP; @@ -611,26 +617,39 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char ** *--stack = (Uint)ArgC; while(*Bases) *--stack = *Bases++; - *--stack = 0; // Return Address Proc_StartProcess(ss, (Uint)stack, 0x202, cs, Entrypoint); } void Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) { - if( CS != 0x1B || SS != 0x23 ) { + if( !(CS == 0x1B || CS == 0x2B) || SS != 0x23 ) { Log_Error("Proc", "Proc_StartProcess: CS / SS are not valid (%x, %x)", CS, SS); Threads_Exit(0, -1); } -// MAGIC_BREAK(); - __asm__ __volatile__ ( - "mov %0, %%rsp;\n\t" // Set stack pointer - "mov %1, %%r11;\n\t" // Set stack pointer - "sysret;\n\t" - : : "r" (Stack), "c" (IP), "r" (Flags) - : "r11" - ); + Log("Proc_StartProcess: (SS=%x, Stack=%p, Flags=%x, CS=%x, IP=%p)", + SS, Stack, Flags, CS, IP); + if(CS == 0x1B) + { + // 32-bit return + __asm__ __volatile__ ( + "mov %0, %%rsp;\n\t" // Set stack pointer + "mov %2, %%r11;\n\t" // Set RFLAGS + "sysret;\n\t" + : : "r" (Stack), "c" (IP), "r" (Flags) + ); + } + else + { + // 64-bit return + __asm__ __volatile__ ( + "mov %0, %%rsp;\n\t" // Set stack pointer + "mov %2, %%r11;\n\t" // Set RFLAGS + "sysretq;\n\t" + : : "r" (Stack), "c" (IP), "r" (Flags) + ); + } for(;;); } @@ -680,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 @@ -704,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 { @@ -719,61 +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" - "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), "a" (0) - ); - for(;;); // Shouldn't reach here + Proc_Reschedule(); } // === EXPORTS ===