Kernel/x86 - Removed PAE support
[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         mov ecx, edx
190         shr ecx, 22
191         test BYTE [0xFC3F0000+ecx*4], 1
192         jnz .justKillIt
193         ; - Page
194         mov ecx, edx
195         shr ecx, 12
196         test BYTE [0xFC000000+ecx*4], 1
197         jnz .justKillIt
198         ; Adjust
199         sub edx, 8
200         ; - Page Table
201         mov ecx, edx
202         shr ecx, 22
203         test BYTE [0xFC3F0000+ecx*4], 1
204         jnz .justKillIt
205         ; - Page
206         mov ecx, edx
207         shr ecx, 12
208         test BYTE [0xFC000000+ecx*4], 1
209         jnz .justKillIt
210         
211         ; Get and alter User SP
212         mov edi, edx
213         mov edx, [ebp+12]       ; Get parameter
214         mov [edi+4], edx        ; save to user stack
215         mov [edi], DWORD User_Syscall_RetAndExit        ; Return Address
216         
217         ; Restore Segment Registers
218         mov ax, 0x23
219         mov ds, ax
220         mov es, ax
221         mov fs, ax
222         mov gs, ax
223         
224         push 0x23       ; SS
225         push edi        ; ESP
226         push 0x202      ; EFLAGS (IP and Rsvd)
227         push 0x1B       ; CS
228         mov eax, [ebp+8]        ; Method to call
229         push eax        ; EIP
230         
231         iret
232         
233         ; Just kill the bleeding thing
234         ; (I know it calls int 0xAC in kernel mode, but meh)
235 .justKillIt:
236         xor eax, eax
237         xor ebx, ebx
238         dec ebx ; EBX = -1
239         int 0xAC
240
241 [global GetCPUNum]
242 GetCPUNum:      ; TODO: Store in debug registers
243 ;       xor eax, eax
244 ;       str ax
245 ;       sub ax, 0x30
246 ;       shr ax, 3       ; ax /= 8
247         mov eax, dr1
248         ret
249
250 [extern GetEIP]
251 [global GetEIP_Sched]
252 [global GetEIP_Sched_ret]
253 GetEIP_Sched_ret equ GetEIP_Sched.ret
254 GetEIP_Sched:
255         call GetEIP
256 GetEIP_Sched.ret:
257         ret
258
259 ; Usermode code exported by the kernel
260 [section .usertext]
261 ; Export a place for the user to jump to to call a syscall
262 ; - Allows the kernel to change the method easily
263 User_Syscall:
264         xchg bx, bx     ; MAGIC BREAKPOINT
265         int 0xAC
266
267 ; A place to return to and exit
268 User_Syscall_RetAndExit:
269         push eax
270         call User_Syscall_Exit
271 User_Syscall_Exit:
272         xor eax, eax
273         mov ebx, [esp+4]
274         int 0xAC

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