X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fproc.asm;h=e0598a5569bd6246c259709740b84daeae67818c;hb=de2ae10743172075f2d527780bdfd890ccddb8e7;hp=b1843c782c33570f0371e5bc3c6396c7d49a9c5c;hpb=b2b9acdf26d6b525f09545b0d07845fde997873b;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/proc.asm b/Kernel/arch/x86/proc.asm index b1843c78..e0598a55 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,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 + 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,39 @@ 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 + 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