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

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