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

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