Kernel/x86_64 - Fix task switching
[tpg/acess2.git] / KernelLand / Kernel / arch / x86_64 / proc.c
index 48504a8..7c73bf9 100644 (file)
@@ -37,7 +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 Uint    Proc_CloneInt(Uint *RSP, Uint *CR3, int bCopyUserVM);
 extern void    NewTaskHeader(void);    // Actually takes cdecl args
 extern void    Proc_InitialiseSSE(void);
 extern void    Proc_SaveSSE(Uint DestPtr);
@@ -75,6 +75,7 @@ void  Proc_StartProcess(Uint16 SS, Uint Stack, Uint Flags, Uint16 CS, Uint IP) NO
 //void Proc_DumpThreadCPUState(tThread *Thread);
 //void Proc_Reschedule(void);
 void   Proc_Scheduler(int CPU, Uint RSP, Uint RIP);
+Uint   Proc_int_SetIRQIP(Uint RIP);
 
 // === GLOBALS ===
 //!\brief Used by desctab.asm in SyscallStub
@@ -323,7 +324,7 @@ void ArchThreads_Init(void)
        outb(0x40, (PIT_TIMER_DIVISOR>>8)&0xFF);        // High Byte
        
        // Create Per-Process Data Block
-       if( !MM_Allocate(MM_PPD_CFG) )
+       if( !MM_Allocate( (void*)MM_PPD_CFG ) )
        {
                Warning("Oh, hell, Unable to allocate PPD for Thread#0");
        }
@@ -457,9 +458,8 @@ void Proc_ClearThread(tThread *Thread)
 tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
 {
        Uint    rsp;
-       tThread *newThread, *cur;
+       tThread *newThread;
        
-       cur = Proc_GetCurThread();
        newThread = Threads_CloneTCB(0);
        if(!newThread)  return -1;
        
@@ -507,8 +507,11 @@ tTID Proc_Clone(Uint Flags)
        if(!newThread)  return -1;
        
        // Save core machine state
-       rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3);
-       if(rip == 0)    return 0;       // Child
+       rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3, !!(Flags & CLONE_NOUSER));
+       if(rip == 0) {
+               SHORTREL(&glThreadListLock);
+               return 0;       // Child
+       }
        newThread->KernelStack = cur->KernelStack;
        newThread->SavedState.RIP = rip;
        newThread->SavedState.SSE = NULL;
@@ -536,11 +539,9 @@ tTID Proc_Clone(Uint Flags)
  */
 tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
 {
-       tThread *new, *cur;
+       tThread *new;
        Uint    stack_contents[3];
 
-       cur = Proc_GetCurThread();
-       
        // Create new thread
        new = Threads_CloneThreadZero();
        if(!new) {
@@ -575,39 +576,39 @@ tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
  */
 Uint Proc_MakeUserStack(void)
 {
-        int    i;
-       Uint    base = USER_STACK_TOP - USER_STACK_SZ;
+       tPage   *base = (void*)(USER_STACK_TOP - USER_STACK_SZ);
        
        // Check Prospective Space
-       for( i = USER_STACK_SZ >> 12; i--; )
+       for( int i = USER_STACK_SZ/PAGE_SIZE; i--; )
        {
-               if( MM_GetPhysAddr( (void*)(base + (i<<12)) ) != 0 )
-                       break;
+               if( MM_GetPhysAddr( base + i ) != 0 )
+               {
+                       return 0;
+               }
        }
        
-       if(i != -1)     return 0;
-       
        // Allocate Stack - Allocate incrementally to clean up MM_Dump output
        // - Most of the user stack is the zero page
-       for( i = 0; i < (USER_STACK_SZ-USER_STACK_PREALLOC)/0x1000; i++ )
+       int i = 0;
+       for( ; i < (USER_STACK_SZ-USER_STACK_PREALLOC)/PAGE_SIZE; i++ )
        {
-               MM_AllocateZero( base + (i<<12) );
+               MM_AllocateZero( base + i );
        }
        // - but the top USER_STACK_PREALLOC pages are actually allocated
-       for( ; i < USER_STACK_SZ/0x1000; i++ )
+       for( ; i < USER_STACK_SZ/PAGE_SIZE; i++ )
        {
-               tPAddr  alloc = MM_Allocate( base + (i<<12) );
+               tPAddr  alloc = MM_Allocate( base + i );
                if( !alloc )
                {
                        // Error
-                       Log_Error("Proc", "Unable to allocate user stack (%i pages requested)", USER_STACK_SZ/0x1000);
+                       Log_Error("Proc", "Unable to allocate user stack (%i pages requested)", USER_STACK_SZ/PAGE_SIZE);
                        while( i -- )
-                               MM_Deallocate( base + (i<<12) );
+                               MM_Deallocate( base + i );
                        return 0;
                }
        }
        
-       return base + USER_STACK_SZ;
+       return (tVAddr)( base + USER_STACK_SZ/PAGE_SIZE );
 }
 
 void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, const char **ArgV, int DataSize)
@@ -725,67 +726,73 @@ void Proc_CallFaultHandler(tThread *Thread)
 
 void Proc_DumpThreadCPUState(tThread *Thread)
 {
-       Log("  At %04x:%016llx", Thread->SavedState.UserCS, Thread->SavedState.UserRIP);
+       if( Thread->CurCPU == GetCPUNum() ) {
+               // TODO: Backtrace to IRQ
+               Log("  IRQ %016llx", Thread->SavedState.UserRIP);
+       }
+       else {
+               Log("  At %016llx, SP=%016llx", Thread->SavedState.RIP, Thread->SavedState.RSP);
+               Log("  User %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(CPU_HAS_LOCK(&glThreadListLock))
+               return;
+       SHORTLOCK(&glThreadListLock);
 
-       if(nextthread == curthread)     return ;
+       tThread *curthread = gaCPUs[cpu].Current;
+       tThread *nextthread = Threads_GetNextToRun(cpu, curthread);
+       
        if(!nextthread)
                nextthread = gaCPUs[cpu].IdleThread;
-       if(!nextthread)
-               return ;
-
-       #if DEBUG_TRACE_SWITCH
-       LogF("\nSwitching to task CR3 = 0x%x, RIP = %p, RSP = %p - %i (%s)\n",
-               nextthread->Process->MemState.CR3,
-               nextthread->SavedState.RIP,
-               nextthread->SavedState.RSP,
-               nextthread->TID,
-               nextthread->ThreadName
-               );
-       #endif
-
-       // Update CPU state
-       gaCPUs[cpu].Current = nextthread;
-       gTSSs[cpu].RSP0 = nextthread->KernelStack-4;
-       __asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
 
-       if( curthread )
+       if(nextthread && nextthread != curthread)
        {
-               // Save FPU/MMX/XMM/SSE state
-               if( curthread->SavedState.SSE )
+               #if DEBUG_TRACE_SWITCH
+               LogF("\nSwitching to task CR3 = 0x%x, RIP = %p, RSP = %p - %i (%s)\n",
+                       nextthread->Process->MemState.CR3,
+                       nextthread->SavedState.RIP,
+                       nextthread->SavedState.RSP,
+                       nextthread->TID,
+                       nextthread->ThreadName
+                       );
+               #endif
+
+               // Update CPU state
+               gaCPUs[cpu].Current = nextthread;
+               gTSSs[cpu].RSP0 = nextthread->KernelStack-sizeof(void*);
+               __asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
+
+               if( curthread )
                {
-                       Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
-                       curthread->SavedState.bSSEModified = 0;
-                       Proc_DisableSSE();
+                       // Save FPU/MMX/XMM/SSE state
+                       if( curthread->SavedState.SSE )
+                       {
+                               Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
+                               curthread->SavedState.bSSEModified = 0;
+                               Proc_DisableSSE();
+                       }
+                       SwitchTasks(
+                               nextthread->SavedState.RSP, &curthread->SavedState.RSP,
+                               nextthread->SavedState.RIP, &curthread->SavedState.RIP,
+                               nextthread->Process->MemState.CR3
+                               );
+               }
+               else
+               {
+                       Uint    tmp;
+                       SwitchTasks(
+                               nextthread->SavedState.RSP, &tmp,
+                               nextthread->SavedState.RIP, &tmp,
+                               nextthread->Process->MemState.CR3
+                               );
                }
-               SwitchTasks(
-                       nextthread->SavedState.RSP, &curthread->SavedState.RSP,
-                       nextthread->SavedState.RIP, &curthread->SavedState.RIP,
-                       nextthread->Process->MemState.CR3
-                       );
-       }
-       else
-       {
-               Uint    tmp;
-               SwitchTasks(
-                       nextthread->SavedState.RSP, &tmp,
-                       nextthread->SavedState.RIP, &tmp,
-                       nextthread->Process->MemState.CR3
-                       );
        }
-       return ;
+       SHORTREL(&glThreadListLock);
 }
 
 /**
@@ -825,5 +832,14 @@ void Proc_Scheduler(int CPU, Uint RSP, Uint RIP)
 #endif
 }
 
+Uint Proc_int_SetIRQIP(Uint RIP)
+{
+        int    cpu = GetCPUNum();
+       tThread *thread = gaCPUs[cpu].Current;
+       Uint    rv = thread->SavedState.UserRIP;
+       thread->SavedState.UserRIP = RIP;
+       return rv;
+}
+
 // === EXPORTS ===
 EXPORT(Proc_SpawnWorker);

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