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

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