a07bdad840809b7e71c24a104b196dbe0cbb7c1d
[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+8]: handler to use
162         ; [EBP+12]: parameter
163         ; [EBP+16]: kernel stack top
164         
165         ;call Proc_GetCurThread
166         
167         ; EAX is the current thread
168         ;mov ebx, eax
169         ;mov eax, [ebx+12*4]    ; Get Kernel Stack
170         mov eax, [ebp+16]       ; Get Kernel Stack
171         sub eax, KSTACK_USERSTATE_SIZE
172         
173         ;
174         ; NOTE: This can cause corruption if the signal happens while the user
175         ;       has called a kernel operation.
176         ; Good thing this can only be called on a user fault.
177         ;
178         
179         ; Validate user ESP
180         ; - Page Table
181         mov edx, [eax+KSTACK_USERSTATE_SIZE-12] ; User ESP is at top of kstack - 3*4
182         %if USE_PAE
183         %error PAE Support
184         %else
185         mov ecx, edx
186         shr ecx, 22
187         test BYTE [0xFC3F0000+ecx*4], 1
188         jnz .justKillIt
189         %endif
190         ; - Page
191         mov ecx, edx
192         shr ecx, 12
193         test BYTE [0xFC000000+ecx*4], 1
194         jnz .justKillIt
195         ; Adjust
196         sub edx, 8
197         ; - Page Table
198         %if USE_PAE
199         %else
200         mov ecx, edx
201         shr ecx, 22
202         test BYTE [0xFC3F0000+ecx*4], 1
203         jnz .justKillIt
204         %endif
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
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 ; Usermode code exported by the kernel
251 [section .usertext]
252 ; Export a place for the user to jump to to call a syscall
253 ; - Allows the kernel to change the method easily
254 User_Syscall:
255         xchg bx, bx     ; MAGIC BREAKPOINT
256         int 0xAC
257
258 ; A place to return to and exit
259 User_Syscall_RetAndExit:
260         push eax
261         call User_Syscall_Exit
262 User_Syscall_Exit:
263         xor eax, eax
264         mov ebx, [esp+4]
265         int 0xAC

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