Unborking some threading code
[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         mov eax, dr0
78         push eax        ; Debug Register 0, Current Thread
79         
80         mov ax, 0x10
81         mov ds, ax
82         mov es, ax
83         mov fs, ax
84         mov gs, ax
85         
86         %if USE_MP
87         call GetCPUNum
88         mov ebx, eax
89         push eax        ; Push as argument
90         %else
91         push 0
92         %endif
93         
94         call Proc_Scheduler
95         
96         add esp, 4      ; Remove Argument
97
98         %if USE_MP
99         test ebx, ebx
100         jnz .sendEOI
101         %endif
102         
103         mov al, 0x20
104         out 0x20, al            ; ACK IRQ
105         %if USE_MP
106         jmp .ret
107         
108 .sendEOI:
109         mov eax, DWORD [gpMP_LocalAPIC]
110         mov DWORD [eax+0x0B0], 0
111         %endif
112 .ret:
113         pop eax ; Debug Register 0, Current Thread
114         mov dr0, eax
115
116         pop gs
117         pop fs
118         pop es
119         pop ds
120         
121         popa
122         add esp, 4      ; CPU ID
123         ; No Error code / int num
124         iret
125
126 [extern Proc_Clone]
127 [extern Threads_Exit]
128 [global SpawnTask]
129 SpawnTask:
130         ; Call Proc_Clone with Flags=0
131         xor eax, eax
132         push eax
133         push eax
134         call Proc_Clone
135         add esp, 8      ; Remove arguments from stack
136         
137         test eax, eax
138         jnz .parent
139         
140         ; In child, so now set up stack frame
141         mov ebx, [esp+4]        ; Child Function
142         mov edx, [esp+8]        ; Argument
143         ; Child
144         push edx        ; Argument
145         call ebx        ; Function
146         push eax        ; Exit Code
147         push   0        ; Kill this thread
148         call Threads_Exit       ; Kill Thread
149         
150 .parent:
151         ret
152
153 ;
154 ; Calls a user fault handler
155 ;
156 [global Proc_ReturnToUser]
157 [extern Proc_GetCurThread]
158 Proc_ReturnToUser:
159         ; EBP is the handler to use
160         
161         call Proc_GetCurThread
162         
163         ; EAX is the current thread
164         mov ebx, eax
165         mov eax, [ebx+40]       ; Get Kernel Stack
166         sub eax, KSTACK_USERSTATE_SIZE
167         
168         ;
169         ; NOTE: This can cause corruption if the signal happens while the user
170         ;       has called a kernel operation.
171         ; Good thing this can only be called on a user fault.
172         ;
173         
174         ; Validate user ESP
175         ; - Page Table
176         mov edx, [eax+KSTACK_USERSTATE_SIZE-12] ; User ESP is at top of kstack - 3*4
177         %if USE_PAE
178         %error PAE Support
179         %else
180         mov ecx, edx
181         shr ecx, 22
182         test BYTE [0xFC3F0000+ecx*4], 1
183         jnz .justKillIt
184         %endif
185         ; - Page
186         mov ecx, edx
187         shr ecx, 12
188         test BYTE [0xFC000000+ecx*4], 1
189         jnz .justKillIt
190         ; Adjust
191         sub edx, 8
192         ; - Page Table
193         %if USE_PAE
194         %else
195         mov ecx, edx
196         shr ecx, 22
197         test BYTE [0xFC3F0000+ecx*4], 1
198         jnz .justKillIt
199         %endif
200         ; - Page
201         mov ecx, edx
202         shr ecx, 12
203         test BYTE [0xFC000000+ecx*4], 1
204         jnz .justKillIt
205         
206         ; Get and alter User SP
207         mov ecx, edx
208         mov edx, [ebx+68]       ; Get Signal Number from TCB (TODO: Get this from parameters)
209         mov [ecx+4], edx        ; Parameter (Signal/Error Number)
210         mov [ecx], DWORD User_Syscall_RetAndExit        ; Return Address
211         
212         ; Restore Segment Registers
213         mov ax, 0x23
214         mov ds, ax
215         mov es, ax
216         mov fs, ax
217         mov gs, ax
218         
219         push 0x23       ; SS
220         push ecx        ; ESP
221         push 0x202      ; EFLAGS (IP and Rsvd)
222         push 0x1B       ; CS
223         push ebp        ; EIP
224         
225         iret
226         
227         ; Just kill the bleeding thing
228         ; (I know it calls int 0xAC in kernel mode, but meh)
229 .justKillIt:
230         xor eax, eax
231         xor ebx, ebx
232         dec ebx
233         int 0xAC
234
235 [global GetCPUNum]
236 GetCPUNum:
237         xor eax, eax
238         str ax
239         sub ax, 0x30
240         shr ax, 3       ; ax /= 8
241         ret
242
243 ; Usermode code exported by the kernel
244 [section .usertext]
245 ; Export a place for the user to jump to to call a syscall
246 ; - Allows the kernel to change the method easily
247 User_Syscall:
248         xchg bx, bx
249         int 0xAC
250
251 ; A place to return to and exit
252 User_Syscall_RetAndExit:
253         push eax
254         call User_Syscall_Exit
255 User_Syscall_Exit:
256         xor eax, eax
257         mov ebx, [esp+4]
258         int 0xAC

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