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

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