X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Farch%2Fx86%2Fproc.asm;h=1987166d6c2ff1d6e5a8a120eaea6b62c7e89288;hb=14d0ba44433f0f828aff710184fd3c597ab73999;hp=8da797110977532a8e0c7f56f6fe8e28a4cac5d9;hpb=51ab5f489bc356940c95cc936fd0508e8f07ea97;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/arch/x86/proc.asm b/KernelLand/Kernel/arch/x86/proc.asm index 8da79711..1987166d 100644 --- a/KernelLand/Kernel/arch/x86/proc.asm +++ b/KernelLand/Kernel/arch/x86/proc.asm @@ -1,5 +1,6 @@ ; AcessOS Microkernel Version ; Start.asm +%include "arch/x86/common.inc.asm" [bits 32] @@ -11,19 +12,6 @@ KSTACK_USERSTATE_SIZE equ (4+8+1+5)*4 ; SRegs, GPRegs, CPU, IRET [section .text] -[global NewTaskHeader] -NewTaskHeader: - mov eax, [esp] - mov dr0, eax - - mov eax, [esp+4] - add esp, 12 ; Thread, Function, Arg Count - call eax - - push eax ; Ret val - push 0 ; 0 = This Thread - call Threads_Exit - [extern MM_Clone] [global Proc_CloneInt] Proc_CloneInt: @@ -38,7 +26,7 @@ Proc_CloneInt: mov esi, [esp+0x20+8] mov [esi], eax ; Undo the pusha - add esp, 0x20 + popa mov eax, .newTask ret .newTask: @@ -53,7 +41,7 @@ Proc_CloneInt: ; +16 = Old RIP save loc ; +20 = CR3 SwitchTasks: - pusha + PUSH_CC ; Old IP mov eax, [esp+0x20+16] @@ -78,7 +66,7 @@ SwitchTasks: jmp ecx .restore: - popa + POP_CC xor eax, eax ret @@ -122,17 +110,8 @@ Proc_RestoreSSE: [extern Isr240.jmp] [global SetAPICTimerCount] SetAPICTimerCount: - pusha - push ds - push es - push fs - push gs - - mov ax, 0x10 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax + PUSH_CC + PUSH_SEG mov eax, [gpMP_LocalAPIC] mov ecx, [eax+0x320] @@ -152,7 +131,7 @@ SetAPICTimerCount: mov DWORD [eax+0x380], 0 ; Update Timer IRQ to the IRQ code - mov eax, SchedulerBase + mov eax, Proc_EventTimer_PIT sub eax, Isr240.jmp+5 mov DWORD [Isr240.jmp+1], eax @@ -160,80 +139,108 @@ SetAPICTimerCount: .ret: mov dx, 0x20 mov al, 0x20 - out dx, al ; ACK IRQ - pop gs - pop fs - pop es - pop ds - popa + out 0x20, al ; ACK IRQ + POP_SEG + POP_CC add esp, 8 ; CPU ID / Error Code iret %endif -; -------------- -; Task Scheduler -; -------------- -[extern Proc_Scheduler] -[global SchedulerBase] -SchedulerBase: - pusha - push ds - push es - push fs - push gs + +%if USE_MP +[global Proc_EventTimer_LAPIC] +Proc_EventTimer_LAPIC: + push eax + mov eax, SS:[gpMP_LocalAPIC] + mov DWORD SS:[eax + 0xB0], 0 + pop eax + jmp Proc_EventTimer_Common +%endif +[global Proc_EventTimer_PIT] +Proc_EventTimer_PIT: + push eax + mov al, 0x20 + out 0x20, al ; ACK IRQ + pop eax + jmp Proc_EventTimer_Common +[extern Proc_HandleEventTimer] +[global Proc_EventTimer_Common] +Proc_EventTimer_Common: + PUSH_CC + PUSH_SEG + ; Clear the Trace/Trap flag pushf and BYTE [esp+1], 0xFE ; Clear Trap Flag popf - - mov eax, dr0 - push eax ; Debug Register 0, Current Thread - - mov ax, 0x10 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax + ; Re-enable interrupts + ; - TODO: This is quite likely racy, if we get an interrupt flood + sti %if USE_MP call GetCPUNum - mov ebx, eax push eax ; Push as argument %else push 0 %endif - call Proc_Scheduler + call Proc_HandleEventTimer [global scheduler_return] scheduler_return: ; Used by some hackery in Proc_DumpThreadCPUState - add esp, 4 ; Remove CPU Number (thread is poped later) - %if USE_MP - test ebx, ebx - jnz .sendEOI - %endif + jmp ReturnFromInterrupt + +; +; Returns after an interrupt, restoring the user state +; - Also handles signal handlers +; +[global ReturnFromInterrupt] +[extern Threads_GetPendingSignal] +[extern Threads_GetSignalHandler] +[extern Proc_CallUser] +ReturnFromInterrupt: + ; Check that we're returning to userland + test DWORD [esp+(4+8+2+1)*4], 0x07 + jz .ret ; Kernel interrupted, return + + call Threads_GetPendingSignal + ; eax: signal number + test eax, eax + jz .ret - mov al, 0x20 - out 0x20, al ; ACK IRQ - %if USE_MP - jmp .ret + ; There's a signal pending, funtime + push eax + call Threads_GetSignalHandler + ; eax: signal handler + pop ecx + test eax, eax + jz .ret + cmp eax, -1 + jz .default + + ; (some stack abuse) + push User_RestoreState + push ecx + mov ecx, esp + + push (2+4+8+2+2)*4 ; Up to and incl. CS + push ecx ; User stack data base + push DWORD [ecx+(2+4+8+2+3)*4] ; User SP + push eax ; handler + call Proc_CallUser + ; Oh, ... it failed. Default time? + add esp, (4+2)*4 +.default: -.sendEOI: - mov eax, DWORD [gpMP_LocalAPIC] - mov DWORD [eax+0x0B0], 0 - %endif -.ret: - pop eax ; Debug Register 0, Current Thread - mov dr0, eax + ; Fall through to return +.ret: pop gs pop fs pop es pop ds - popa - add esp, 4*2 ; CPU ID + Dummy error code - ; No Error code / int num + add esp, 2*4 ; IRQ Num / CPU ID + error code iret [extern Proc_Clone] @@ -286,52 +293,17 @@ Proc_ReturnToUser: ; Good thing this can only be called on a user fault. ; - ; Validate user ESP - ; - Page Table - mov edx, [eax+KSTACK_USERSTATE_SIZE-12] ; User ESP is at top of kstack - 3*4 - mov ecx, edx - shr ecx, 22 - test BYTE [0xFC3F0000+ecx*4], 1 - jnz .justKillIt - ; - Page - mov ecx, edx - shr ecx, 12 - test BYTE [0xFC000000+ecx*4], 1 - jnz .justKillIt - ; Adjust - sub edx, 8 - ; - Page Table - mov ecx, edx - shr ecx, 22 - test BYTE [0xFC3F0000+ecx*4], 1 - jnz .justKillIt - ; - Page - mov ecx, edx - shr ecx, 12 - test BYTE [0xFC000000+ecx*4], 1 - jnz .justKillIt - - ; Get and alter User SP - mov edi, edx - mov edx, [ebp+12] ; Get parameter - mov [edi+4], edx ; save to user stack - mov [edi], DWORD User_Syscall_RetAndExit ; Return Address - - ; Restore Segment Registers - mov ax, 0x23 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - - push 0x23 ; SS - push edi ; ESP - push 0x202 ; EFLAGS (IP and Rsvd) - push 0x1B ; CS - mov eax, [ebp+8] ; Method to call - push eax ; EIP - - iret + ; Create data to add to user stack + push DWORD [ebp+12] + push User_Syscall_RetAndExit + mov ecx, esp + + ; Call user method + push 2*4 + push ecx + push DWORD [eax+KSTACK_USERSTATE_SIZE-12] ; User ESP is at top of kstack - 3*4 + push DWORD [ebp+8] + call Proc_CallUser ; Just kill the bleeding thing ; (I know it calls int 0xAC in kernel mode, but meh) @@ -363,6 +335,24 @@ User_Syscall: xchg bx, bx ; MAGIC BREAKPOINT int 0xAC +[global User_Signal_Kill] +User_Signal_Kill: + xor eax, eax + mov bl, [esp+4] + mov bh, 0x02 + int 0xAC + jmp $ + +User_RestoreState: + pop gs + pop fs + pop es + pop ds + popa + add esp, 2*4 ; Kernel's error code and interrupt number + retf ; EFLAGS/SS/ESP were not included in the state + + ; A place to return to and exit User_Syscall_RetAndExit: push eax