Kernel/x86 - Cleaning up dead code
[tpg/acess2.git] / Kernel / arch / x86 / proc.asm
1 ; AcessOS Microkernel Version
2 ; Start.asm
3
4 [bits 32]
5
6 %define SAVEFLAG_FPU    0x1
7
8 KERNEL_BASE     equ 0xC0000000
9
10 KSTACK_USERSTATE_SIZE   equ     (4+8+1+5)*4     ; SRegs, GPRegs, CPU, IRET
11
12 [section .text]
13
14 [global NewTaskHeader]
15 NewTaskHeader:
16         mov eax, [esp]
17         mov dr0, eax
18
19         mov eax, [esp+4]
20         add esp, 12     ; Thread, Function, Arg Count
21         call eax
22         
23         push eax        ; Ret val
24         push 0          ; 0 = This Thread
25         call Threads_Exit
26
27 [extern MM_Clone]
28 [global Proc_CloneInt]
29 Proc_CloneInt:
30         pusha
31         ; Save RSP
32         mov eax, [esp+0x20+4]
33         mov [eax], esp
34         call MM_Clone
35         ; Save CR3
36         mov esi, [esp+0x20+8]
37         mov [esi], eax
38         ; Undo the pusha
39         add esp, 0x20
40         mov eax, .newTask
41         ret
42 .newTask:
43         popa
44         xor eax, eax
45         ret
46
47 [global SwitchTasks]
48 ; + 4 = New RSP
49 ; + 8 = Old RSP save loc
50 ; +12 = New RIP
51 ; +16 = Old RIP save loc
52 ; +20 = CR3
53 SwitchTasks:
54         pusha
55         
56         ; Old IP
57         mov eax, [esp+0x20+16]
58         test eax, eax
59         jz .nosave
60         mov DWORD [eax], .restore
61         ; Old SP
62         mov eax, [esp+0x20+8]
63         mov [eax], esp
64
65 .nosave:
66         mov ecx, [esp+0x20+12]  ; New IP
67         mov eax, [esp+0x20+20]  ; New CR3
68         mov esp, [esp+0x20+ 4]  ; New SP
69         
70         test eax, eax
71         jz .setState
72         mov cr3, eax
73         invlpg [esp]
74         invlpg [esp+0x1000]
75 .setState:
76         jmp ecx
77
78 .restore:
79         popa
80         xor eax, eax
81         ret
82
83 [global Proc_InitialiseSSE]
84 Proc_InitialiseSSE:
85         mov eax, cr4
86         or eax, (1 << 9)|(1 << 10)      ; Set OSFXSR and OSXMMEXCPT
87         mov cr4, eax
88         mov eax, cr0
89         and ax, ~(1 << 2)       ; Clear EM
90         or eax, (1 << 1)        ; Set MP
91         mov eax, cr0
92         ret
93 [global Proc_DisableSSE]
94 Proc_DisableSSE:
95         mov eax, cr0
96         or ax, 1 << 3   ; Set TS
97         mov cr0, eax
98         ret
99 [global Proc_EnableSSE]
100 Proc_EnableSSE:
101         mov eax, cr0
102         and ax, ~(1 << 3)       ; Clear TS
103         mov cr0, eax
104         ret
105
106 [global Proc_SaveSSE]
107 Proc_SaveSSE:
108         mov eax, [esp+4]
109         fxsave [eax]
110         ret
111 [global Proc_RestoreSSE]
112 Proc_RestoreSSE:
113         mov eax, [esp+4]
114         fxrstor [eax]
115         ret
116
117 %if USE_MP
118 [extern giMP_TimerCount]
119 [extern gpMP_LocalAPIC]
120 [extern Isr240.jmp]
121 [global SetAPICTimerCount]
122 SetAPICTimerCount:
123         pusha
124         push ds
125         push es
126         push fs
127         push gs
128         
129         mov ax, 0x10
130         mov ds, ax
131         mov es, ax
132         mov fs, ax
133         mov gs, ax
134         
135         mov eax, [gpMP_LocalAPIC]
136         mov ecx, [eax+0x320]
137         test ecx, 0x00010000
138         jz .setTime
139         mov DWORD [eax+0x380], 0xFFFFFFFF       ; Set Initial Count
140         mov DWORD [eax+0x320], 0x000000F0       ; Enable the timer on IVT#0xEF (One Shot)
141         jmp .ret
142
143 .setTime:       
144         ; Get Timer Count
145         mov ecx, 0xFFFFFFFF
146         sub ecx, [eax+0x390]
147         mov DWORD [giMP_TimerCount], ecx
148         ; Disable APIC Timer
149         mov DWORD [eax+0x320], 0x000100EF
150         mov DWORD [eax+0x380], 0
151
152         ; Update Timer IRQ to the IRQ code
153         mov eax, SchedulerBase
154         sub eax, Isr240.jmp+5
155         mov DWORD [Isr240.jmp+1], eax
156
157         ;xchg bx, bx    ; MAGIC BREAK
158 .ret:
159         mov dx, 0x20
160         mov al, 0x20
161         out dx, al              ; ACK IRQ
162         pop gs
163         pop fs
164         pop es
165         pop ds
166         popa
167         add esp, 8      ; CPU ID / Error Code
168         iret
169 %endif
170 ; --------------
171 ; Task Scheduler
172 ; --------------
173 [extern Proc_Scheduler]
174 [global SchedulerBase]
175 SchedulerBase:
176         pusha
177         push ds
178         push es
179         push fs
180         push gs
181         
182         pushf
183         and BYTE [esp+1], 0xFE  ; Clear Trap Flag
184         popf
185         
186         mov eax, dr0
187         push eax        ; Debug Register 0, Current Thread
188         
189         mov ax, 0x10
190         mov ds, ax
191         mov es, ax
192         mov fs, ax
193         mov gs, ax
194         
195         %if USE_MP
196         call GetCPUNum
197         mov ebx, eax
198         push eax        ; Push as argument
199         %else
200         push 0
201         %endif
202         
203         call Proc_Scheduler
204 [global scheduler_return]
205 scheduler_return:       ; Used by some hackery in Proc_DumpThreadCPUState
206         
207         add esp, 4      ; Remove CPU Number (thread is poped later)
208
209         %if USE_MP
210         test ebx, ebx
211         jnz .sendEOI
212         %endif
213         
214         mov al, 0x20
215         out 0x20, al            ; ACK IRQ
216         %if USE_MP
217         jmp .ret
218         
219 .sendEOI:
220         mov eax, DWORD [gpMP_LocalAPIC]
221         mov DWORD [eax+0x0B0], 0
222         %endif
223 .ret:
224         pop eax ; Debug Register 0, Current Thread
225         mov dr0, eax
226
227         pop gs
228         pop fs
229         pop es
230         pop ds
231         
232         popa
233         add esp, 4*2    ; CPU ID + Dummy error code
234         ; No Error code / int num
235         iret
236
237 [extern Proc_Clone]
238 [extern Threads_Exit]
239 [global SpawnTask]
240 SpawnTask:
241         ; Call Proc_Clone with Flags=0
242         xor eax, eax
243 ;       push eax
244         push eax
245         call Proc_Clone
246         add esp, 8      ; Remove arguments from stack
247         
248         test eax, eax
249         jnz .parent
250         
251         ; In child, so now set up stack frame
252         mov ebx, [esp+4]        ; Child Function
253         mov edx, [esp+8]        ; Argument
254         ; Child Function
255         push edx        ; Argument
256         call ebx        ; Function
257         ; Kill thread once done
258         push eax        ; Exit Code
259         push   0        ; Kill this thread
260         call Threads_Exit       ; Kill Thread
261         
262 .parent:
263         ret
264
265 ; void Proc_ReturnToUser(void *Method, Uint Parameter)
266 ; Calls a user fault handler
267 ;
268 [global Proc_ReturnToUser]
269 [extern Proc_GetCurThread]
270 Proc_ReturnToUser:
271         push ebp
272         mov ebp, esp
273         ; [EBP+8]: handler to use
274         ; [EBP+12]: parameter
275         ; [EBP+16]: kernel stack top
276         
277         ;call Proc_GetCurThread
278         
279         ; EAX is the current thread
280         ;mov ebx, eax
281         ;mov eax, [ebx+12*4]    ; Get Kernel Stack
282         mov eax, [ebp+16]       ; Get Kernel Stack
283         sub eax, KSTACK_USERSTATE_SIZE
284         
285         ;
286         ; NOTE: This can cause corruption if the signal happens while the user
287         ;       has called a kernel operation.
288         ; Good thing this can only be called on a user fault.
289         ;
290         
291         ; Validate user ESP
292         ; - Page Table
293         mov edx, [eax+KSTACK_USERSTATE_SIZE-12] ; User ESP is at top of kstack - 3*4
294         mov ecx, edx
295         shr ecx, 22
296         test BYTE [0xFC3F0000+ecx*4], 1
297         jnz .justKillIt
298         ; - Page
299         mov ecx, edx
300         shr ecx, 12
301         test BYTE [0xFC000000+ecx*4], 1
302         jnz .justKillIt
303         ; Adjust
304         sub edx, 8
305         ; - Page Table
306         mov ecx, edx
307         shr ecx, 22
308         test BYTE [0xFC3F0000+ecx*4], 1
309         jnz .justKillIt
310         ; - Page
311         mov ecx, edx
312         shr ecx, 12
313         test BYTE [0xFC000000+ecx*4], 1
314         jnz .justKillIt
315         
316         ; Get and alter User SP
317         mov edi, edx
318         mov edx, [ebp+12]       ; Get parameter
319         mov [edi+4], edx        ; save to user stack
320         mov [edi], DWORD User_Syscall_RetAndExit        ; Return Address
321         
322         ; Restore Segment Registers
323         mov ax, 0x23
324         mov ds, ax
325         mov es, ax
326         mov fs, ax
327         mov gs, ax
328         
329         push 0x23       ; SS
330         push edi        ; ESP
331         push 0x202      ; EFLAGS (IP and Rsvd)
332         push 0x1B       ; CS
333         mov eax, [ebp+8]        ; Method to call
334         push eax        ; EIP
335         
336         iret
337         
338         ; Just kill the bleeding thing
339         ; (I know it calls int 0xAC in kernel mode, but meh)
340 .justKillIt:
341         xor eax, eax
342         xor ebx, ebx
343         dec ebx ; EBX = -1
344         int 0xAC
345
346 [global GetCPUNum]
347 GetCPUNum:      ; TODO: Store in debug registers
348 ;       xor eax, eax
349 ;       str ax
350 ;       sub ax, 0x30
351 ;       shr ax, 3       ; ax /= 8
352         mov eax, dr1
353         ret
354
355 [extern GetEIP]
356 [global GetEIP_Sched]
357 [global GetEIP_Sched_ret]
358 GetEIP_Sched_ret equ GetEIP_Sched.ret
359 GetEIP_Sched:
360         call GetEIP
361 GetEIP_Sched.ret:
362         ret
363
364 ; Usermode code exported by the kernel
365 [section .usertext]
366 ; Export a place for the user to jump to to call a syscall
367 ; - Allows the kernel to change the method easily
368 User_Syscall:
369         xchg bx, bx     ; MAGIC BREAKPOINT
370         int 0xAC
371
372 ; A place to return to and exit
373 User_Syscall_RetAndExit:
374         push eax
375         call User_Syscall_Exit
376 User_Syscall_Exit:
377         xor eax, eax
378         mov ebx, [esp+4]
379         int 0xAC
380
381 ; vim: ft=nasm ts=8

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