X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fproc.c;h=f9c5ba1fcaf4f004881c140e90bb6fc2e17050bc;hb=47e9dfd89189fc6b150bd6b20229cb047c7e0858;hp=f7bda0fca98725835316947867fe951e8937c1a9;hpb=9d3800f60f2212432e550a4e003ae65b498a4d36;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index f7bda0fc..f9c5ba1f 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -34,6 +34,7 @@ extern tThread *gDeleteThreads; extern tThread *Threads_GetNextToRun(int CPU); extern void Threads_Dump(); extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags); +extern void Isr7(); // === PROTOTYPES === void ArchThreads_Init(); @@ -60,6 +61,13 @@ tTSS *gTSSs = NULL; #if !USE_MP tTSS gTSS0 = {0}; #endif +// --- Error Recovery --- +char gaDoubleFaultStack[1024]; +tTSS gDoubleFault_TSS = { + .ESP0 = (Uint)&gaDoubleFaultStack[1023], + .SS0 = 0x10, + .EIP = (Uint)Isr7 +}; // === CODE === /** @@ -106,6 +114,15 @@ void ArchThreads_Init() #if USE_MP } + // Initialise Double Fault TSS + gGDT[5].LimitLow = sizeof(tTSS); + gGDT[5].LimitHi = 0; + gGDT[5].Access = 0x89; // Type + gGDT[5].Flags = 0x4; + gGDT[5].BaseLow = (Uint)&gDoubleFault_TSS & 0xFFFF; + gGDT[5].BaseMid = (Uint)&gDoubleFault_TSS >> 16; + gGDT[5].BaseHi = (Uint)&gDoubleFault_TSS >> 24; + // Initialise TSS for(pos=0;pos> 16; - gGDT[5+pos].BaseHi = (Uint)&gTSSs[pos] >> 24; + gGDT[6+pos].LimitLow = sizeof(tTSS); + gGDT[6+pos].LimitHi = 0; + gGDT[6+pos].Access = 0x89; // Type + gGDT[6+pos].Flags = 0x4; + gGDT[6+pos].BaseLow = (Uint)&gTSSs[pos] & 0xFFFF; + gGDT[6+pos].BaseMid = (Uint)&gTSSs[pos] >> 16; + gGDT[6+pos].BaseHi = (Uint)&gTSSs[pos] >> 24; #if USE_MP } for(pos=0;posTID; } +/** + * \fn int Proc_SpawnWorker() + * \brief Spawns a new worker thread + */ +int Proc_SpawnWorker() +{ + tThread *new, *cur; + Uint eip, esp, ebp; + + cur = Proc_GetCurThread(); + + // Create new thread + new = malloc( sizeof(tThread) ); + if(!new) { + Warning("Proc_SpawnWorker - Out of heap space!\n"); + return -1; + } + memcpy(new, &gThreadZero, sizeof(tThread)); + // Set Thread ID + new->TID = giNextTID++; + // Set kernel stack + new->KernelStack = MM_NewWorkerStack(); + + // Get ESP and EBP based in the new stack + __asm__ __volatile__ ("mov %%esp, %0": "=r"(esp)); + __asm__ __volatile__ ("mov %%ebp, %0": "=r"(ebp)); + esp = cur->KernelStack - (new->KernelStack - esp); + ebp = new->KernelStack - (cur->KernelStack - ebp); + + // Save core machine state + new->SavedState.ESP = esp; + new->SavedState.EBP = ebp; + eip = GetEIP(); + if(eip == SWITCH_MAGIC) { + outb(0x20, 0x20); // ACK Timer and return as child + return 0; + } + + // Set EIP as parent + new->SavedState.EIP = eip; + + return new->TID; +} + /** * \fn Uint Proc_MakeUserStack() * \brief Creates a new user stack @@ -325,7 +386,7 @@ Uint Proc_MakeUserStack() /** - * \fn void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, char **ArgV, char **EnvP, int DataSize) + * \fn void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize) * \brief Starts a user task */ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char **EnvP, int DataSize) @@ -396,6 +457,8 @@ void Proc_StartUser(Uint Entrypoint, Uint *Bases, int ArgC, char **ArgV, char ** * \fn int Proc_Demote(Uint *Err, int Dest, tRegs *Regs) * \brief Demotes a process to a lower permission level * \param Err Pointer to user's errno + * \param Dest New Permission Level + * \param Regs Pointer to user's register structure */ int Proc_Demote(Uint *Err, int Dest, tRegs *Regs) { @@ -497,10 +560,14 @@ void Proc_Scheduler(int CPU) __asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->MemState.CR3)); // Switch threads __asm__ __volatile__ ( - "mov %1, %%esp\n\t" - "mov %2, %%ebp\n\t" - "jmp *%3" : : + "mov %1, %%esp\n\t" // Restore ESP + "mov %2, %%ebp\n\t" // and EBP + "jmp *%3" : : // And return to where we saved state (Proc_Clone or Proc_Scheduler) "a"(SWITCH_MAGIC), "b"(gCurrentThread->SavedState.ESP), - "d"(gCurrentThread->SavedState.EBP), "c"(gCurrentThread->SavedState.EIP)); + "d"(gCurrentThread->SavedState.EBP), "c"(gCurrentThread->SavedState.EIP) + ); for(;;); // Shouldn't reach here } + +// === EXPORTS === +EXPORT(Proc_SpawnWorker);