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

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