1 ; AcessOS Microkernel Version
6 %define SAVEFLAG_FPU 0x1
8 KERNEL_BASE equ 0xC0000000
10 KSTACK_USERSTATE_SIZE equ (4+8+1+5)*4 ; SRegs, GPRegs, CPU, IRET
14 [global NewTaskHeader]
20 add esp, 12 ; Thread, Function, Arg Count
24 push 0 ; 0 = This Thread
28 [global Proc_CloneInt]
34 push DWORD [esp+0x20+12]
51 ; + 8 = Old RSP save loc
53 ; +16 = Old RIP save loc
59 mov eax, [esp+0x20+16]
62 mov DWORD [eax], .restore
68 mov ecx, [esp+0x20+12] ; New IP
69 mov eax, [esp+0x20+20] ; New CR3
70 mov esp, [esp+0x20+ 4] ; New SP
85 [global Proc_InitialiseSSE]
88 or eax, (1 << 9)|(1 << 10) ; Set OSFXSR and OSXMMEXCPT
91 and ax, ~(1 << 2) ; Clear EM
92 or eax, (1 << 1) ; Set MP
95 [global Proc_DisableSSE]
98 or ax, 1 << 3 ; Set TS
101 [global Proc_EnableSSE]
104 and ax, ~(1 << 3) ; Clear TS
108 [global Proc_SaveSSE]
113 [global Proc_RestoreSSE]
120 [extern giMP_TimerCount]
121 [extern gpMP_LocalAPIC]
123 [global SetAPICTimerCount]
137 mov eax, [gpMP_LocalAPIC]
141 mov DWORD [eax+0x380], 0xFFFFFFFF ; Set Initial Count
142 mov DWORD [eax+0x320], 0x000000F0 ; Enable the timer on IVT#0xEF (One Shot)
149 mov DWORD [giMP_TimerCount], ecx
151 mov DWORD [eax+0x320], 0x000100EF
152 mov DWORD [eax+0x380], 0
154 ; Update Timer IRQ to the IRQ code
155 mov eax, SchedulerBase
156 sub eax, Isr240.jmp+5
157 mov DWORD [Isr240.jmp+1], eax
159 ;xchg bx, bx ; MAGIC BREAK
169 add esp, 8 ; CPU ID / Error Code
175 [extern Proc_Scheduler]
176 [global SchedulerBase]
185 and BYTE [esp+1], 0xFE ; Clear Trap Flag
189 push eax ; Debug Register 0, Current Thread
200 push eax ; Push as argument
206 [global scheduler_return]
207 scheduler_return: ; Used by some hackery in Proc_DumpThreadCPUState
209 add esp, 4 ; Remove CPU Number (thread is poped later)
217 out 0x20, al ; ACK IRQ
222 mov eax, DWORD [gpMP_LocalAPIC]
223 mov DWORD [eax+0x0B0], 0
226 pop eax ; Debug Register 0, Current Thread
235 add esp, 4*2 ; CPU ID + Dummy error code
236 ; No Error code / int num
240 [extern Threads_Exit]
243 ; Call Proc_Clone with Flags=0
248 add esp, 8 ; Remove arguments from stack
253 ; In child, so now set up stack frame
254 mov ebx, [esp+4] ; Child Function
255 mov edx, [esp+8] ; Argument
259 ; Kill thread once done
261 push 0 ; Kill this thread
262 call Threads_Exit ; Kill Thread
267 ; void Proc_ReturnToUser(void *Method, Uint Parameter, tVAddr KernelStack)
268 ; Calls a user fault handler
270 [global Proc_ReturnToUser]
271 [extern Proc_GetCurThread]
275 ; [EBP+8]: handler to use
276 ; [EBP+12]: parameter
277 ; [EBP+16]: kernel stack top
281 sub eax, KSTACK_USERSTATE_SIZE
284 ; NOTE: This can cause corruption if the signal happens while the user
285 ; has called a kernel operation.
286 ; Good thing this can only be called on a user fault.
291 mov edx, [eax+KSTACK_USERSTATE_SIZE-12] ; User ESP is at top of kstack - 3*4
294 test BYTE [0xFC3F0000+ecx*4], 1
299 test BYTE [0xFC000000+ecx*4], 1
306 test BYTE [0xFC3F0000+ecx*4], 1
311 test BYTE [0xFC000000+ecx*4], 1
314 ; Get and alter User SP
316 mov edx, [ebp+12] ; Get parameter
317 mov [edi+4], edx ; save to user stack
318 mov [edi], DWORD User_Syscall_RetAndExit ; Return Address
320 ; Restore Segment Registers
329 push 0x202 ; EFLAGS (IP and Rsvd)
331 mov eax, [ebp+8] ; Method to call
336 ; Just kill the bleeding thing
337 ; (I know it calls int 0xAC in kernel mode, but meh)
345 GetCPUNum: ; TODO: Store in debug registers
350 [global GetEIP_Sched]
351 [global GetEIP_Sched_ret]
352 GetEIP_Sched_ret equ GetEIP_Sched.ret
358 ; Usermode code exported by the kernel
360 ; Export a place for the user to jump to to call a syscall
361 ; - Allows the kernel to change the method easily
363 xchg bx, bx ; MAGIC BREAKPOINT
366 ; A place to return to and exit
367 User_Syscall_RetAndExit:
369 call User_Syscall_Exit