Kernel/x86_64 - More bugfixes, I suspect the PMM code is borken
authorJohn Hodge <[email protected]>
Sat, 12 Nov 2011 08:51:55 +0000 (16:51 +0800)
committerJohn Hodge <[email protected]>
Sat, 12 Nov 2011 08:51:55 +0000 (16:51 +0800)
Kernel/arch/x86_64/errors.c
Kernel/arch/x86_64/include/proc.h
Kernel/arch/x86_64/mm_virt.c
Kernel/arch/x86_64/proc.asm
Kernel/arch/x86_64/proc.c

index d1856db..f7da7f9 100644 (file)
@@ -5,12 +5,15 @@
 #include <acess.h>
 #include <proc.h>
 #include <mm_virt.h>
+#include <threads_int.h>       // Needed for SSE handling
 
 #define MAX_BACKTRACE  6
 
 // === IMPORTS ===
- int   MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs);
-void   Error_Backtrace(Uint IP, Uint BP);
+extern int     MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs);
+extern void    Error_Backtrace(Uint IP, Uint BP);
+extern void    Proc_EnableSSE(void);
+extern void    Proc_RestoreSSE(Uint32 Data);
 
 // === PROTOTYPES ===
 void   Error_Handler(tRegs *Regs);
@@ -31,6 +34,23 @@ const char * const csaERROR_NAMES[] = {
 void Error_Handler(tRegs *Regs)
 {
        Uint    cr;
+
+       if( Regs->IntNum == 7 )
+       {
+               tThread *thread = Proc_GetCurThread();
+               if(!thread->SavedState.bSSEModified)
+               {
+                       Proc_EnableSSE();
+                       if(!thread->SavedState.SSE)
+                               thread->SavedState.SSE = malloc(sizeof(tSSEState) + 0xF);
+                       else
+                               Proc_RestoreSSE( ((Uint)thread->SavedState.SSE + 0xF) & ~0xF );
+                       thread->SavedState.bSSEModified = 1;
+//                     __asm__ __volatile__ ("sti");
+                       return ;
+               }
+               // oops, SSE enabled but a #NM, bad news
+       }
        
        if( Regs->IntNum == 14 ) {
                __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
@@ -44,7 +64,7 @@ void Error_Handler(tRegs *Regs)
        }
        
        Log("CPU Error %x, Code: 0x%x", Regs->IntNum, Regs->ErrorCode);
-//     Log(" - %s", csaERROR_NAMES[Regs->IntNum]);
+       Log(" - %s", csaERROR_NAMES[Regs->IntNum]);
        Log(" CS:RIP = 0x%04x:%016llx", Regs->CS, Regs->RIP);
        Log(" SS:RSP = 0x%04x:%016llx", Regs->SS, Regs->RSP);
        Log(" RFLAGS = 0x%016llx", Regs->RFlags);
index 2173c34..dad8f06 100644 (file)
@@ -33,6 +33,12 @@ typedef struct sMemoryState
        tPAddr  CR3;
 }      tMemoryState;
 
+// 512 bytes, 16 byte aligned
+typedef struct sSSEState
+{
+       char    data[512];
+} tSSEState;
+
 /**
  * \brief Task state for thread handler
  */
@@ -40,6 +46,8 @@ typedef struct sTaskState
 {
        Uint    RIP, RSP;
        Uint64  UserRIP, UserCS;
+       tSSEState       *SSE;
+        int    bSSEModified;
 }      tTaskState;
 
 // === CONSTANTS ===
index aca3728..511803c 100644 (file)
@@ -100,6 +100,8 @@ void MM_FinishVirtualInit(void)
 void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable )
 {
        tPAddr  curpage = *Ent & PADDR_MASK; 
+        int    bCopied = 0;
+       
        if( MM_GetRefCount( curpage ) <= 0 ) {
                Log_KernelPanic("MMVirt", "Page %P still marked COW, but unreferenced", curpage);
        }
@@ -107,7 +109,7 @@ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable
        {
                *Ent &= ~PF_COW;
                *Ent |= PF_PRESENT|PF_WRITE;
-//             Log_Debug("MMVirt", "COW ent at %p (%p) only %P", Ent, NextLevel, curpage);
+               Log_Debug("MMVirt", "COW ent at %p (%p) only %P", Ent, NextLevel, curpage);
        }
        else
        {
@@ -125,23 +127,28 @@ void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable
                memcpy( tmp, NextLevel, 0x1000 );
                MM_FreeTemp( (tVAddr)tmp );
                
-//             Log_Debug("MMVirt", "COW ent at %p (%p) from %P to %P", Ent, NextLevel, curpage, paddr);
+               Log_Debug("MMVirt", "COW ent at %p (%p) from %P to %P", Ent, NextLevel, curpage, paddr);
 
                MM_DerefPhys( curpage );
                *Ent &= PF_USER;
                *Ent |= paddr|PF_PRESENT|PF_WRITE;
+               
+               bCopied = 1;
        }
        INVLPG( (tVAddr)NextLevel );
        
-       // Mark COW on pages
+       // Mark COW on contents if it's a PDPT, Dir or Table
        if(bTable) 
        {
                Uint64  *dp = NextLevel;
                 int    i;
                for( i = 0; i < 512; i ++ )
                {
-                       if( !(dp[i] & PF_PRESENT) )     continue;
-                       MM_RefPhys( dp[i] & PADDR_MASK );
+                       if( !(dp[i] & PF_PRESENT) )
+                               continue;
+                       
+                       if( bCopied )
+                               MM_RefPhys( dp[i] & PADDR_MASK );
                        if( dp[i] & PF_WRITE ) {
                                dp[i] &= ~PF_WRITE;
                                dp[i] |= PF_COW;
index e6db3ce..db22a16 100644 (file)
@@ -127,4 +127,36 @@ SwitchTasks:
        xor eax, eax    ; Return zero
        ret
 
+[global Proc_InitialiseSSE]
+Proc_InitialiseSSE:
+       mov rax, cr4
+       or ax, (1 << 9)|(1 << 10)       ; Set OSFXSR and OSXMMEXCPT
+       mov cr4, rax
+       mov rax, cr0
+       and ax, ~(1 << 2)       ; Clear EM
+       or rax, (1 << 1)        ; Set MP
+       mov rax, cr0
+       ret
+[global Proc_DisableSSE]
+Proc_DisableSSE:
+       mov rax, cr0
+       or ax, 1 << 3   ; Set TS
+       mov cr0, rax
+       ret
+[global Proc_EnableSSE]
+Proc_EnableSSE:
+       mov rax, cr0
+       and ax, ~(1 << 3)       ; Clear TS
+       mov cr0, rax
+       ret
+
+[global Proc_SaveSSE]
+Proc_SaveSSE:
+       fxsave [rdi]
+       ret
+[global Proc_RestoreSSE]
+Proc_RestoreSSE:
+       fxrstor [rdi]
+       ret
+
 ; vim: ft=nasm
index 75778c2..3594552 100644 (file)
@@ -39,6 +39,9 @@ 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 void    Proc_InitialiseSSE(void);
+extern void    Proc_SaveSSE(Uint DestPtr);
+extern void    Proc_DisableSSE(void);
 
 extern Uint64  gInitialPML4[512];      // start.asm
 extern int     giNumCPUs;
@@ -322,6 +325,8 @@ void ArchThreads_Init(void)
                Warning("Oh, hell, Unable to allocate PPD for Thread#0");
        }
 
+       Proc_InitialiseSSE();
+
        Log_Log("Proc", "Multithreading initialised");
 }
 
@@ -467,6 +472,7 @@ int Proc_NewKThread(void (*Fcn)(void*), void *Data)
        
        newThread->SavedState.RSP = rsp;
        newThread->SavedState.RIP = (Uint)&NewTaskHeader;
+       newThread->SavedState.SSE = NULL;
 //     Log("New (KThread) %p, rsp = %p\n", newThread->SavedState.RIP, newThread->SavedState.RSP);
        
 //     MAGIC_BREAK();  
@@ -499,6 +505,7 @@ int Proc_Clone(Uint Flags)
        if(rip == 0)    return 0;       // Child
        newThread->KernelStack = cur->KernelStack;
        newThread->SavedState.RIP = rip;
+       newThread->SavedState.SSE = NULL;
 
        // DEBUG
        #if 0
@@ -550,6 +557,7 @@ int Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
 
        new->SavedState.RSP = new->KernelStack - sizeof(stack_contents);
        new->SavedState.RIP = (Uint)&NewTaskHeader;
+       new->SavedState.SSE = NULL;
        
 //     Log("New (Worker) %p, rsp = %p\n", new->SavedState.RIP, new->SavedState.RSP);
        
@@ -598,13 +606,11 @@ Uint Proc_MakeUserStack(void)
        return base + USER_STACK_SZ;
 }
 
-
 void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, char **ArgV, int DataSize)
 {
        Uint    *stack;
-       char    **envp;
         int    i;
-       Uint    delta;
+       char    **envp = NULL;
        Uint16  ss, cs;
        
        
@@ -615,17 +621,18 @@ void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, char **ArgV, int DataS
                Threads_Exit(0, -1);
        }
        stack -= (DataSize+7)/8;
-       LOG("stack = 0x%x", stack);
-       Log("stack = %p, DataSize = %i", stack, DataSize);
        memcpy( stack, ArgV, DataSize );
        free(ArgV);
        
        // Adjust Arguments and environment
-       delta = (Uint)stack - (Uint)ArgV;
-       ArgV = (char**)stack;
-       for( i = 0; ArgV[i]; i++ )      ArgV[i] += delta;
-       envp = &ArgV[i+1];
-       for( i = 0; envp[i]; i++ )      envp[i] += delta;
+       if(DataSize)
+       {
+               Uint    delta = (Uint)stack - (Uint)ArgV;
+               ArgV = (char**)stack;
+               for( i = 0; ArgV[i]; i++ )      ArgV[i] += delta;
+               envp = &ArgV[i+1];
+               for( i = 0; envp[i]; i++ )      envp[i] += delta;
+       }
        
        // User Mode Segments
        // 0x2B = 64-bit
@@ -750,6 +757,14 @@ 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 )
+       {
+               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,

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