X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fproc.asm;h=944b24dd4d5cd16cdd825515b5b8ca365df7a8fd;hb=3764c294f21229bdf700f436fa4884f5e76e0d3a;hp=b1843c782c33570f0371e5bc3c6396c7d49a9c5c;hpb=b2b9acdf26d6b525f09545b0d07845fde997873b;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/proc.asm b/Kernel/arch/x86/proc.asm index b1843c78..944b24dd 100644 --- a/Kernel/arch/x86/proc.asm +++ b/Kernel/arch/x86/proc.asm @@ -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,29 +74,58 @@ SchedulerBase: push fs push gs + 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 - 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 +[global scheduler_return] +scheduler_return: ; Used by some hackery in Proc_DumpThreadCPUState - add esp, 4 ; Remove Argument + add esp, 4 ; Remove CPU Number (thread is poped later) + + %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 + add esp, 4*2 ; CPU ID + Dummy error code ; No Error code / int num iret @@ -63,29 +146,36 @@ SpawnTask: ; In child, so now set up stack frame mov ebx, [esp+4] ; Child Function mov edx, [esp+8] ; Argument - ; Child + ; Child Function push edx ; Argument call ebx ; Function + ; Kill thread once done + 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+8]: handler to use + ; [EBP+12]: parameter + ; [EBP+16]: kernel stack top - call Proc_GetCurThread - xchg bx, bx + ;call Proc_GetCurThread ; EAX is the current thread - mov ebx, eax - mov eax, [ebx+40] ; Get Kernel Stack - sub eax, KSTACK_USERSTATE_SIZE + ;mov ebx, eax + ;mov eax, [ebx+12*4] ; Get Kernel Stack + mov eax, [ebp+16] ; Get Kernel Stack + sub eax, KSTACK_USERSTATE_SIZE ; ; NOTE: This can cause corruption if the signal happens while the user @@ -93,12 +183,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+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 @@ -108,15 +229,49 @@ 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+8] ; 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 ; EBX = -1 + 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 +[extern GetEIP] +[global GetEIP_Sched] +[global GetEIP_Sched_ret] +GetEIP_Sched_ret equ GetEIP_Sched.ret +GetEIP_Sched: + call GetEIP +GetEIP_Sched.ret: + 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