Kernel/x86 - Clean up some of the task switching code (possibly a little broken)
[tpg/acess2.git] / KernelLand / Kernel / arch / x86 / proc.asm
index 8da7971..1987166 100644 (file)
@@ -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

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