Multiple IPStack Related changes (and other bugfixes)
[tpg/acess2.git] / Kernel / arch / x86 / proc.asm
index b1843c7..fd372db 100644 (file)
@@ -8,6 +8,60 @@ KERNEL_BASE    equ 0xC0000000
 KSTACK_USERSTATE_SIZE  equ     (4+8+1+5)*4     ; SRegs, GPRegs, CPU, IRET
 
 [section .text]
+%if USE_MP
+[extern giMP_TimerCount]
+[extern gpMP_LocalAPIC]
+[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
+       
+       mov eax, [gpMP_LocalAPIC]
+       mov ecx, [eax+0x320]
+       test ecx, 0x00010000
+       jz .setTime
+       mov DWORD [eax+0x380], 0xFFFFFFFF       ; Set Initial Count
+       mov DWORD [eax+0x320], 0x000000F0       ; Enable the timer on IVT#0xEF (One Shot)
+       jmp .ret
+
+.setTime:      
+       ; Get Timer Count
+       mov ecx, 0xFFFFFFFF
+       sub ecx, [eax+0x390]
+       mov DWORD [giMP_TimerCount], ecx
+       ; Disable APIC Timer
+       mov DWORD [eax+0x320], 0x000100EF
+       mov DWORD [eax+0x380], 0
+
+       ; Update Timer IRQ to the IRQ code
+       mov eax, SchedulerBase
+       sub eax, Isr240.jmp+5
+       mov DWORD [Isr240.jmp+1], eax
+
+       ;xchg bx, bx    ; MAGIC BREAK
+.ret:
+       mov dx, 0x20
+       mov al, 0x20
+       out dx, al              ; ACK IRQ
+       pop gs
+       pop fs
+       pop es
+       pop ds
+       popa
+       add esp, 4      ; CPU ID
+       ; No Error code / int num
+       iret
+%endif
 ; --------------
 ; Task Scheduler
 ; --------------
@@ -20,27 +74,50 @@ SchedulerBase:
        push fs
        push gs
        
+       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
        
-       mov eax, [esp+12*4]     ; CPU Number
-       push eax        ; Pus as argument
+       %if USE_MP
+       call GetCPUNum
+       mov ebx, eax
+       push eax        ; Push as argument
+       %else
+       push 0
+       %endif
        
        call Proc_Scheduler
        
        add esp, 4      ; Remove Argument
+
+       %if USE_MP
+       test ebx, ebx
+       jnz .sendEOI
+       %endif
        
+       mov al, 0x20
+       out 0x20, al            ; ACK IRQ
+       %if USE_MP
+       jmp .ret
+       
+.sendEOI:
+       mov eax, DWORD [gpMP_LocalAPIC]
+       mov DWORD [eax+0x0B0], 0
+       %endif
+.ret:
+       pop eax ; Debug Register 0, Current Thread
+       mov dr0, eax
+
        pop gs
        pop fs
        pop es
        pop ds
-
-       mov dx, 0x20
-       mov al, 0x20
-       out dx, al              ; ACK IRQ
+       
        popa
        add esp, 4      ; CPU ID
        ; No Error code / int num
@@ -66,26 +143,30 @@ SpawnTask:
        ; Child
        push edx        ; Argument
        call ebx        ; Function
+       push eax        ; Exit Code
+       push   0        ; Kill this thread
        call Threads_Exit       ; Kill Thread
        
 .parent:
        ret
 
-;
+; void Proc_ReturnToUser(void *Method, Uint Parameter)
 ; Calls a user fault handler
 ;
-[global Proc_AlterUserReturnAddr]
+[global Proc_ReturnToUser]
 [extern Proc_GetCurThread]
-Proc_AlterUserReturnAddr:
-       ; EBP is the handler to use
+Proc_ReturnToUser:
+       push ebp
+       mov ebp, esp
+       ; [EBP+4]: handler to use
+       ; [EBP+8]: parameter
        
        call Proc_GetCurThread
-       xchg bx, bx
        
        ; EAX is the current thread
        mov ebx, eax
-       mov eax, [ebx+40]       ; Get Kernel Stack
-       sub eax, KSTACK_USERSTATE_SIZE  
+       mov eax, [ebx+12*4]     ; Get Kernel Stack
+       sub eax, KSTACK_USERSTATE_SIZE
        
        ;
        ; NOTE: This can cause corruption if the signal happens while the user
@@ -93,12 +174,43 @@ Proc_AlterUserReturnAddr:
        ; 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
+       %if USE_PAE
+       %error PAE Support
+       %else
+       mov ecx, edx
+       shr ecx, 22
+       test BYTE [0xFC3F0000+ecx*4], 1
+       jnz .justKillIt
+       %endif
+       ; - Page
+       mov ecx, edx
+       shr ecx, 12
+       test BYTE [0xFC000000+ecx*4], 1
+       jnz .justKillIt
+       ; Adjust
+       sub edx, 8
+       ; - Page Table
+       %if USE_PAE
+       %else
+       mov ecx, edx
+       shr ecx, 22
+       test BYTE [0xFC3F0000+ecx*4], 1
+       jnz .justKillIt
+       %endif
+       ; - Page
+       mov ecx, edx
+       shr ecx, 12
+       test BYTE [0xFC000000+ecx*4], 1
+       jnz .justKillIt
+       
        ; Get and alter User SP
-       mov ecx, [eax+KSTACK_USERSTATE_SIZE-12]
-       mov edx, [ebx+60]       ; Get Signal Number
-       mov [ecx-4], edx
-       mov [ecx-8], DWORD User_Syscall_RetAndExit
-       sub ecx, 8
+       mov edi, edx
+       mov edx, [ebp+8]        ; Get parameter
+       mov [edi+4], edx        ; save to user stack
+       mov [edi], DWORD User_Syscall_RetAndExit        ; Return Address
        
        ; Restore Segment Registers
        mov ax, 0x23
@@ -108,15 +220,40 @@ Proc_AlterUserReturnAddr:
        mov gs, ax
        
        push 0x23       ; SS
-       push ecx        ; ESP
+       push edi        ; ESP
        push 0x202      ; EFLAGS (IP and Rsvd)
        push 0x1B       ; CS
-       push ebp        ; EIP
+       mov eax, [ebp+4]        ; Method to call
+       push eax        ; EIP
        
        iret
+       
+       ; Just kill the bleeding thing
+       ; (I know it calls int 0xAC in kernel mode, but meh)
+.justKillIt:
+       xor eax, eax
+       xor ebx, ebx
+       dec ebx
+       int 0xAC
 
+[global GetCPUNum]
+GetCPUNum:     ; TODO: Store in debug registers
+;      xor eax, eax
+;      str ax
+;      sub ax, 0x30
+;      shr ax, 3       ; ax /= 8
+       mov eax, dr1
+       ret
 
+; Usermode code exported by the kernel
 [section .usertext]
+; Export a place for the user to jump to to call a syscall
+; - Allows the kernel to change the method easily
+User_Syscall:
+       xchg bx, bx     ; MAGIC BREAKPOINT
+       int 0xAC
+
+; A place to return to and exit
 User_Syscall_RetAndExit:
        push eax
        call User_Syscall_Exit

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