Kernel/x86_64 - Updated to new threading changes, fixed some bugs
authorJohn Hodge <[email protected]>
Sun, 29 Jan 2012 14:46:06 +0000 (22:46 +0800)
committerJohn Hodge <[email protected]>
Sun, 29 Jan 2012 14:46:06 +0000 (22:46 +0800)
Kernel/arch/x86_64/mm_virt.c
Kernel/arch/x86_64/proc.asm
Kernel/arch/x86_64/proc.c
Kernel/arch/x86_64/start64.asm

index 511803c..79513b9 100644 (file)
@@ -10,6 +10,9 @@
 #include <proc.h>
 #include <hal_proc.h>
 
+// === DEBUG OPTIONS ===
+#define TRACE_COW      0
+
 // === CONSTANTS ===
 #define PHYS_BITS      52      // TODO: Move out
 #define VIRT_BITS      48
@@ -109,7 +112,9 @@ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable
        {
                *Ent &= ~PF_COW;
                *Ent |= PF_PRESENT|PF_WRITE;
+               #if TRACE_COW
                Log_Debug("MMVirt", "COW ent at %p (%p) only %P", Ent, NextLevel, curpage);
+               #endif
        }
        else
        {
@@ -127,7 +132,9 @@ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable
                memcpy( tmp, NextLevel, 0x1000 );
                MM_FreeTemp( (tVAddr)tmp );
                
+               #if TRACE_COW
                Log_Debug("MMVirt", "COW ent at %p (%p) from %P to %P", Ent, NextLevel, curpage, paddr);
+               #endif
 
                MM_DerefPhys( curpage );
                *Ent &= PF_USER;
@@ -271,8 +278,10 @@ void MM_int_DumpTablesEnt(tVAddr RangeStart, size_t Length, tPAddr Expected)
                LogF("%13s", "zero" );
        else
                LogF("%13llx", PAGETABLE(RangeStart>>12) & PADDR_MASK );
-       LogF(" : 0x%6llx (%c%c%c%c)\r\n",
+       LogF(" : 0x%6llx (%c%c%c%c%c%c)\r\n",
                Length,
+               (Expected & PF_GLOBAL ? 'G' : '-'),
+               (Expected & PF_NX ? '-' : 'x'),
                (Expected & PF_PAGED ? 'p' : '-'),
                (Expected & PF_COW ? 'C' : '-'),
                (Expected & PF_USER ? 'U' : '-'),
@@ -286,13 +295,17 @@ void MM_int_DumpTablesEnt(tVAddr RangeStart, size_t Length, tPAddr Expected)
  */
 void MM_DumpTables(tVAddr Start, tVAddr End)
 {
-       const tPAddr    CHANGEABLE_BITS = ~(PF_PRESENT|PF_WRITE|PF_USER|PF_COW|PF_PAGED) & 0xFFF;
+       const tPAddr    FIXED_BITS = PF_PRESENT|PF_WRITE|PF_USER|PF_COW|PF_PAGED|PF_NX|PF_GLOBAL;
+       const tPAddr    CHANGEABLE_BITS = ~FIXED_BITS & 0xFFF;
        const tPAddr    MASK = ~CHANGEABLE_BITS;        // Physical address and access bits
        tVAddr  rangeStart = 0;
        tPAddr  expected = CHANGEABLE_BITS;     // CHANGEABLE_BITS is used because it's not a vaild value
        tVAddr  curPos;
        Uint    page;
-       
+       tPAddr  expected_pml4 = PF_WRITE|PF_USER;       
+       tPAddr  expected_pdp = PF_WRITE|PF_USER;        
+       tPAddr  expected_pd = PF_WRITE|PF_USER; 
+
        Log("Table Entries: (%p to %p)", Start, End);
        
        End &= (1L << 48) - 1;
@@ -310,13 +323,26 @@ void MM_DumpTables(tVAddr Start, tVAddr End)
                
                // End of a range
                if(!(PAGEMAPLVL4(page>>27) & PF_PRESENT)
+               ||  (PAGEMAPLVL4(page>>27) & FIXED_BITS) != expected_pml4
                || !(PAGEDIRPTR(page>>18) & PF_PRESENT)
+               ||  (PAGEDIRPTR(page>>18) & FIXED_BITS) != expected_pdp
                || !(PAGEDIR(page>>9) & PF_PRESENT)
+               ||  (PAGEDIR(page>>9) & FIXED_BITS) != expected_pd
                || !(PAGETABLE(page) & PF_PRESENT)
-               || (PAGETABLE(page) & MASK) != expected)
+               ||  (PAGETABLE(page) & MASK) != expected)
                {                       
                        if(expected != CHANGEABLE_BITS)
                        {
+                               // Merge
+                               expected &= expected_pml4 | ~(PF_WRITE|PF_USER);
+                               expected &= expected_pdp  | ~(PF_WRITE|PF_USER);
+                               expected &= expected_pd   | ~(PF_WRITE|PF_USER);
+                               expected |= expected_pml4 & PF_NX;
+                               expected |= expected_pdp  & PF_NX;
+                               expected |= expected_pd   & PF_NX;
+                               Log("expected (pml4 = %x, pdp = %x, pd = %x)",
+                                       expected_pml4, expected_pdp, expected_pd);
+                               // Dump
                                MM_int_DumpTablesEnt( rangeStart, curPos - rangeStart, expected );
                                expected = CHANGEABLE_BITS;
                        }
@@ -342,6 +368,9 @@ void MM_DumpTables(tVAddr Start, tVAddr End)
                        if( !(PAGETABLE(page) & PF_PRESENT) )   continue;
                        
                        expected = (PAGETABLE(page) & MASK);
+                       expected_pml4 = (PAGEMAPLVL4(page>>27) & FIXED_BITS);
+                       expected_pdp  = (PAGEDIRPTR (page>>18) & FIXED_BITS);
+                       expected_pd   = (PAGEDIR    (page>> 9) & FIXED_BITS);
                        rangeStart = curPos;
                }
                if(gMM_ZeroPage && (expected & PADDR_MASK) == gMM_ZeroPage )
@@ -351,6 +380,9 @@ void MM_DumpTables(tVAddr Start, tVAddr End)
        }
        
        if(expected != CHANGEABLE_BITS) {
+               // Merge
+               
+               // Dump
                MM_int_DumpTablesEnt( rangeStart, curPos - rangeStart, expected );
                expected = 0;
        }
@@ -413,8 +445,8 @@ int MM_GetPageEntryPtr(tVAddr Addr, BOOL bTemp, BOOL bAllocate, BOOL bLargePage,
                                *ent |= PF_USER;
                        INVLPG( &pmlevels[i+1][ (Addr>>size)*512 ] );
                        memset( &pmlevels[i+1][ (Addr>>size)*512 ], 0, 0x1000 );
-                       LOG("Init PML%i ent 0x%x %p with %P", 4 - i,
-                               Addr>>size, (Addr>>size) << size, tmp);
+                       LOG("Init PML%i ent 0x%x %p with %P (*ent = %P)", 4 - i,
+                               Addr>>size, (Addr>>size) << size, tmp, *ent);
                }
                // Catch large pages
                else if( *ent & PF_LARGE )
@@ -633,6 +665,7 @@ void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
                if( Flags & MM_PFLAG_COW ) {
                        *ent &= ~PF_WRITE;
                        *ent |= PF_COW;
+       INVLPG_ALL();
                }
                else {
                        *ent &= ~PF_COW;
@@ -875,18 +908,21 @@ tPAddr MM_Clone(void)
        INVLPG_ALL();
        
        // #3 Set Copy-On-Write to all user pages
-       for( i = 0; i < 256; i ++)
+       if( Threads_GetPID() != 0 )
        {
-               if( PAGEMAPLVL4(i) & PF_WRITE ) {
-                       PAGEMAPLVL4(i) |= PF_COW;
-                       PAGEMAPLVL4(i) &= ~PF_WRITE;
+               for( i = 0; i < 256; i ++)
+               {
+                       if( PAGEMAPLVL4(i) & PF_WRITE ) {
+                               PAGEMAPLVL4(i) |= PF_COW;
+                               PAGEMAPLVL4(i) &= ~PF_WRITE;
+                       }
+       
+                       TMPMAPLVL4(i) = PAGEMAPLVL4(i);
+//                     Log_Debug("MM", "TMPMAPLVL4(%i) = 0x%016llx", i, TMPMAPLVL4(i));
+                       if( !(TMPMAPLVL4(i) & PF_PRESENT) )     continue ;
+                       
+                       MM_RefPhys( TMPMAPLVL4(i) & PADDR_MASK );
                }
-
-               TMPMAPLVL4(i) = PAGEMAPLVL4(i);
-//             Log_Debug("MM", "TMPMAPLVL4(%i) = 0x%016llx", i, TMPMAPLVL4(i));
-               if( !(TMPMAPLVL4(i) & PF_PRESENT) )     continue ;
-               
-               MM_RefPhys( TMPMAPLVL4(i) & PADDR_MASK );
        }
        
        // #4 Map in kernel pages
@@ -981,11 +1017,13 @@ void MM_ClearUser(void)
 tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize)
 {
        tVAddr  ret;
+       tPAddr  phys;
         int    i;
        
        // #1 Set temp fractal to PID0
        Mutex_Acquire(&glMM_TempFractalLock);
        TMPCR3() = ((tPAddr)gInitialPML4 - KERNEL_BASE) | 3;
+       INVLPG_ALL();
        
        // #2 Scan for a free stack addresss < 2^47
        for(ret = 0x100000; ret < (1ULL << 47); ret += KERNEL_STACK_SIZE)
@@ -1000,31 +1038,35 @@ tVAddr MM_NewWorkerStack(void *StackData, size_t StackSize)
        }
        
        // #3 Map all save the last page in the range
-       //    - This acts as as guard page, and doesn't cost us anything.
+       //  - This acts as as guard page
+       MM_GetPageEntryPtr(ret, 1, 1, 0, NULL); // Make sure tree is allocated
        for( i = 0; i < KERNEL_STACK_SIZE/0x1000 - 1; i ++ )
        {
-               tPAddr  phys = MM_AllocPhys();
+               phys = MM_AllocPhys();
                if(!phys) {
                        // TODO: Clean up
                        Log_Error("MM", "MM_NewWorkerStack - Unable to allocate page");
                        return 0;
                }
                MM_MapEx(ret + i*0x1000, phys, 1, 0);
+               MM_SetFlags(ret + i*0x1000, MM_PFLAG_KERNEL|MM_PFLAG_RO, MM_PFLAG_KERNEL);
        }
 
+       // Copy data
        if( StackSize > 0x1000 ) {
                Log_Error("MM", "MM_NewWorkerStack: StackSize(0x%x) > 0x1000, cbf handling", StackSize);
        }
        else {
-               tPAddr  *ptr, paddr;
-               tVAddr  tmp_addr;
-               MM_GetPageEntryPtr(ret + i*0x1000, 1, 0, 0, &ptr);
-               paddr = *ptr & ~0xFFF;
-               tmp_addr = MM_MapTemp(paddr);
-               memcpy( (void*)(tmp_addr + (0x1000 - StackSize)), StackData, StackSize );
+               tVAddr  tmp_addr, dest;
+               tmp_addr = MM_MapTemp(phys);
+               dest = tmp_addr + (0x1000 - StackSize);
+               memcpy( (void*)dest, StackData, StackSize );
+               Log_Debug("MM", "MM_NewWorkerStack: %p->%p %i bytes (i=%i)", StackData, dest, StackSize, i);
+               Log_Debug("MM", "MM_NewWorkerStack: ret = %p", ret);
                MM_FreeTemp(tmp_addr);
        }
-       
+
+       TMPCR3() = 0;
        Mutex_Release(&glMM_TempFractalLock);
        
        return ret + i*0x1000;
index db22a16..f540b3b 100644 (file)
@@ -14,29 +14,14 @@ GetRIP:
 
 [global NewTaskHeader]
 NewTaskHeader:
-       mov rax, [rsp]
-       mov dr0, rax
-       
-       sti
-       mov al, 0x20
-       mov dx, 0x20
-       out dx, al
+       ; [rsp+0x00]: Thread
+       ; [rsp+0x08]: Function
+       ; [rsp+0x10]: Argument
 
-       mov rdi, [rsp+0x18]
-       dec QWORD [rsp+0x10]
-       jz .call
-       mov rsi, [rsp+0x20]
-       dec QWORD [rsp+0x10]
-       jz .call
-       mov rdx, [rsp+0x28]
-       dec QWORD [rsp+0x10]
-       jz .call
-       mov rcx, [rsp+0x30]
-       dec QWORD [rsp+0x10]
-       jz .call
-.call:
+       mov rdi, [rsp+0x10]
        mov rax, [rsp+0x8]
-;      xchg bx, bx
+       add rsp, 0x10   ; Reclaim stack space (thread/fcn)
+       xchg bx, bx
        call rax
        
        ; Quit thread with RAX as the return code
@@ -113,6 +98,7 @@ SwitchTasks:
        mov cr3, r8
        
        ; Make sure the stack is valid before jumping
+       invlpg [rdi-0x1000]
        invlpg [rdi]
        invlpg [rdi+0x1000]
        
index 3594552..a8928ca 100644 (file)
@@ -49,6 +49,7 @@ extern int    giNextTID;
 extern int     giTotalTickets;
 extern int     giNumActiveThreads;
 extern tThread gThreadZero;
+extern tProcess        gProcessZero;
 extern void    Threads_Dump(void);
 extern void    Proc_ReturnToUser(tVAddr Handler, tVAddr KStackTop, int Argument);
 extern void    Time_UpdateTimestamp(void);
@@ -310,7 +311,7 @@ void ArchThreads_Init(void)
        
        gaCPUs[0].Current = &gThreadZero;
        
-       gThreadZero.MemState.CR3 = (Uint)gInitialPML4 - KERNEL_BASE;
+       gProcessZero.MemState.CR3 = (Uint)gInitialPML4 - KERNEL_BASE;
        gThreadZero.CurCPU = 0;
        gThreadZero.KernelStack = 0xFFFFA00000000000 + KERNEL_STACK_SIZE;
        
@@ -405,6 +406,7 @@ void Proc_Start(void)
        
        // BSP still should run the current task
        gaCPUs[0].Current = &gThreadZero;
+       __asm__ __volatile__ ("mov %0, %%db0" : : "r"(&gThreadZero));
        
        // Start interrupts and wait for APs to come up
        Log("Waiting for APs to come up\n");
@@ -427,24 +429,30 @@ void Proc_Start(void)
 tThread *Proc_GetCurThread(void)
 {
        #if USE_MP
-       return gaCPUs[ GetCPUNum() ].Current;
+       tThread *ret;
+       __asm__ __volatile__ ("mov %%db0, %0" : "=r"(thread));
+       return ret;     // gaCPUs[ GetCPUNum() ].Current;
        #else
        return gaCPUs[ 0 ].Current;
        #endif
 }
 
+void Proc_ClearProcess(tProcess *Process)
+{
+       Log_Warning("Proc", "TODO: Nuke address space etc");
+}
+
 /*
  * 
  */
 void Proc_ClearThread(tThread *Thread)
 {
-       Log_Warning("Proc", "TODO: Nuke address space etc");
 }
 
 /**
  * \brief Create a new kernel thread
  */
-int Proc_NewKThread(void (*Fcn)(void*), void *Data)
+tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
 {
        Uint    rsp;
        tThread *newThread, *cur;
@@ -453,9 +461,6 @@ int Proc_NewKThread(void (*Fcn)(void*), void *Data)
        newThread = Threads_CloneTCB(0);
        if(!newThread)  return -1;
        
-       // Set CR3
-       newThread->MemState.CR3 = cur->MemState.CR3;
-
        // Create new KStack
        newThread->KernelStack = MM_NewKStack();
        // Check for errors
@@ -466,7 +471,6 @@ int Proc_NewKThread(void (*Fcn)(void*), void *Data)
 
        rsp = newThread->KernelStack;
        *(Uint*)(rsp-=8) = (Uint)Data;  // Data (shadowed)
-       *(Uint*)(rsp-=8) = 1;   // Number of params
        *(Uint*)(rsp-=8) = (Uint)Fcn;   // Function to call
        *(Uint*)(rsp-=8) = (Uint)newThread;     // Thread ID
        
@@ -485,7 +489,7 @@ int Proc_NewKThread(void (*Fcn)(void*), void *Data)
  * \fn int Proc_Clone(Uint Flags)
  * \brief Clone the current process
  */
-int Proc_Clone(Uint Flags)
+tTID Proc_Clone(Uint Flags)
 {
        tThread *newThread, *cur = Proc_GetCurThread();
        Uint    rip;
@@ -501,7 +505,7 @@ int Proc_Clone(Uint Flags)
        if(!newThread)  return -1;
        
        // Save core machine state
-       rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->MemState.CR3);
+       rip = Proc_CloneInt(&newThread->SavedState.RSP, &newThread->Process->MemState.CR3);
        if(rip == 0)    return 0;       // Child
        newThread->KernelStack = cur->KernelStack;
        newThread->SavedState.RIP = rip;
@@ -531,28 +535,24 @@ int Proc_Clone(Uint Flags)
 int Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
 {
        tThread *new, *cur;
-       Uint    stack_contents[4];
+       Uint    stack_contents[3];
 
        cur = Proc_GetCurThread();
        
        // Create new thread
-       new = malloc( sizeof(tThread) );
+       new = Threads_CloneThreadZero();
        if(!new) {
                Warning("Proc_SpawnWorker - Out of heap space!\n");
                return -1;
        }
-       memcpy(new, &gThreadZero, sizeof(tThread));
-       // Set Thread ID
-       new->TID = giNextTID++;
 
        // Create the stack contents
-       stack_contents[3] = (Uint)Data;
-       stack_contents[2] = 1;
+       stack_contents[2] = (Uint)Data;
        stack_contents[1] = (Uint)Fcn;
        stack_contents[0] = (Uint)new;
        
        // Create a new worker stack (in PID0's address space)
-       // The stack is relocated by this code
+       // - The stack is built by this code using stack_contents
        new->KernelStack = MM_NewWorkerStack(stack_contents, sizeof(stack_contents));
 
        new->SavedState.RSP = new->KernelStack - sizeof(stack_contents);
@@ -744,7 +744,7 @@ void Proc_Reschedule(void)
 
        #if DEBUG_TRACE_SWITCH
        LogF("\nSwitching to task CR3 = 0x%x, RIP = %p, RSP = %p - %i (%s)\n",
-               nextthread->MemState.CR3,
+               nextthread->Process->MemState.CR3,
                nextthread->SavedState.RIP,
                nextthread->SavedState.RSP,
                nextthread->TID,
@@ -757,19 +757,30 @@ void Proc_Reschedule(void)
        gTSSs[cpu].RSP0 = nextthread->KernelStack-4;
        __asm__ __volatile__ ("mov %0, %%db0" : : "r" (nextthread));
 
-       // Save FPU/MMX/XMM/SSE state
-       if( curthread->SavedState.SSE )
+       if( curthread )
+       {
+               // 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
        {
-               Proc_SaveSSE( ((Uint)curthread->SavedState.SSE + 0xF) & ~0xF );
-               curthread->SavedState.bSSEModified = 0;
-               Proc_DisableSSE();
+               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->MemState.CR3
-               );
        return ;
 }
 
@@ -780,7 +791,6 @@ void Proc_Reschedule(void)
 void Proc_Scheduler(int CPU, Uint RSP, Uint RIP)
 {
 #if 0
-       {
        tThread *thread;
 
        // If the spinlock is set, let it complete
@@ -808,7 +818,6 @@ void Proc_Scheduler(int CPU, Uint RSP, Uint RIP)
        // ACK Timer here?
 
        Proc_Reschedule();
-       }
 #endif
 }
 
index b63b63a..c8e7f9a 100644 (file)
@@ -50,10 +50,7 @@ start64:
 
 [global GetCPUNum]
 GetCPUNum:
-       xor rax, rax
-       str ax
-       sub ax, 0x38    ; TSS Base
-       shr ax, 4       ; One 16-byte TSS per CPU
+       mov rax, dr1
        ret
 
 KSTACK_USERSTATE_SIZE  equ     (5+2+16+2)*8    ; IRET, ErrorNum, ErrorCode, GPRs, FS&GS

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