From: John Hodge Date: Sat, 12 Nov 2011 08:51:55 +0000 (+0800) Subject: Kernel/x86_64 - More bugfixes, I suspect the PMM code is borken X-Git-Tag: rel0.14~108 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=a3ca5c97e1e761815f1890dccdbe9dce243b5c8f;p=tpg%2Facess2.git Kernel/x86_64 - More bugfixes, I suspect the PMM code is borken --- diff --git a/Kernel/arch/x86_64/errors.c b/Kernel/arch/x86_64/errors.c index d1856db1..f7da7f9f 100644 --- a/Kernel/arch/x86_64/errors.c +++ b/Kernel/arch/x86_64/errors.c @@ -5,12 +5,15 @@ #include #include #include +#include // 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); diff --git a/Kernel/arch/x86_64/include/proc.h b/Kernel/arch/x86_64/include/proc.h index 2173c34c..dad8f061 100644 --- a/Kernel/arch/x86_64/include/proc.h +++ b/Kernel/arch/x86_64/include/proc.h @@ -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 === diff --git a/Kernel/arch/x86_64/mm_virt.c b/Kernel/arch/x86_64/mm_virt.c index aca37283..511803cc 100644 --- a/Kernel/arch/x86_64/mm_virt.c +++ b/Kernel/arch/x86_64/mm_virt.c @@ -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; diff --git a/Kernel/arch/x86_64/proc.asm b/Kernel/arch/x86_64/proc.asm index e6db3ce2..db22a162 100644 --- a/Kernel/arch/x86_64/proc.asm +++ b/Kernel/arch/x86_64/proc.asm @@ -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 diff --git a/Kernel/arch/x86_64/proc.c b/Kernel/arch/x86_64/proc.c index 75778c2f..3594552b 100644 --- a/Kernel/arch/x86_64/proc.c +++ b/Kernel/arch/x86_64/proc.c @@ -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,