Multiple IPStack Related changes (and other bugfixes)
[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 ; void Proc_ReturnToUser(void *Method, Uint Parameter)
154 ; Calls a user fault handler
155 ;
156 [global Proc_ReturnToUser]
157 [extern Proc_GetCurThread]
158 Proc_ReturnToUser:
159         push ebp
160         mov ebp, esp
161         ; [EBP+4]: handler to use
162         ; [EBP+8]: parameter
163         
164         call Proc_GetCurThread
165         
166         ; EAX is the current thread
167         mov ebx, eax
168         mov eax, [ebx+12*4]     ; Get Kernel Stack
169         sub eax, KSTACK_USERSTATE_SIZE
170         
171         ;
172         ; NOTE: This can cause corruption if the signal happens while the user
173         ;       has called a kernel operation.
174         ; Good thing this can only be called on a user fault.
175         ;
176         
177         ; Validate user ESP
178         ; - Page Table
179         mov edx, [eax+KSTACK_USERSTATE_SIZE-12] ; User ESP is at top of kstack - 3*4
180         %if USE_PAE
181         %error PAE Support
182         %else
183         mov ecx, edx
184         shr ecx, 22
185         test BYTE [0xFC3F0000+ecx*4], 1
186         jnz .justKillIt
187         %endif
188         ; - Page
189         mov ecx, edx
190         shr ecx, 12
191         test BYTE [0xFC000000+ecx*4], 1
192         jnz .justKillIt
193         ; Adjust
194         sub edx, 8
195         ; - Page Table
196         %if USE_PAE
197         %else
198         mov ecx, edx
199         shr ecx, 22
200         test BYTE [0xFC3F0000+ecx*4], 1
201         jnz .justKillIt
202         %endif
203         ; - Page
204         mov ecx, edx
205         shr ecx, 12
206         test BYTE [0xFC000000+ecx*4], 1
207         jnz .justKillIt
208         
209         ; Get and alter User SP
210         mov edi, edx
211         mov edx, [ebp+8]        ; Get parameter
212         mov [edi+4], edx        ; save to user stack
213         mov [edi], DWORD User_Syscall_RetAndExit        ; Return Address
214         
215         ; Restore Segment Registers
216         mov ax, 0x23
217         mov ds, ax
218         mov es, ax
219         mov fs, ax
220         mov gs, ax
221         
222         push 0x23       ; SS
223         push edi        ; ESP
224         push 0x202      ; EFLAGS (IP and Rsvd)
225         push 0x1B       ; CS
226         mov eax, [ebp+4]        ; Method to call
227         push eax        ; EIP
228         
229         iret
230         
231         ; Just kill the bleeding thing
232         ; (I know it calls int 0xAC in kernel mode, but meh)
233 .justKillIt:
234         xor eax, eax
235         xor ebx, ebx
236         dec ebx
237         int 0xAC
238
239 [global GetCPUNum]
240 GetCPUNum:      ; TODO: Store in debug registers
241 ;       xor eax, eax
242 ;       str ax
243 ;       sub ax, 0x30
244 ;       shr ax, 3       ; ax /= 8
245         mov eax, dr1
246         ret
247
248 ; Usermode code exported by the kernel
249 [section .usertext]
250 ; Export a place for the user to jump to to call a syscall
251 ; - Allows the kernel to change the method easily
252 User_Syscall:
253         xchg bx, bx     ; MAGIC BREAKPOINT
254         int 0xAC
255
256 ; A place to return to and exit
257 User_Syscall_RetAndExit:
258         push eax
259         call User_Syscall_Exit
260 User_Syscall_Exit:
261         xor eax, eax
262         mov ebx, [esp+4]
263         int 0xAC

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