Usermode/libc - Fix strchr and strrchr behavior
[tpg/acess2.git] / KernelLand / Kernel / arch / x86_64 / desctab.asm
1 ;
2 ;
3 ;
4 %include "arch/x86_64/include/common.inc.asm"
5 [BITS 64]
6
7 [extern Log]
8 [extern Log_Debug]
9 [extern gGDTPtr]
10 [extern gGDT]
11
12 %define NUM_IRQ_CALLBACKS       4
13
14 MM_LOCALAPIC    equ     0xFFFFFD0000000000
15
16 [section .text]
17 [global Desctab_Init]
18 Desctab_Init:   
19         ; Save to make following instructions smaller
20         mov rdi, gIDT
21         
22         ; Set an IDT entry to a callback
23         %macro SETIDT 2
24         mov rax, %2
25         mov WORD [rdi + %1*16], ax
26         shr rax, 16
27         mov WORD [rdi + %1*16 + 6], ax
28         shr rax, 16
29         mov DWORD [rdi + %1*16 + 8], eax
30         ; Enable
31         mov ax, WORD [rdi + %1*16 + 4]
32         or  ax, 0x8000
33         mov WORD [rdi + %1*16 + 4], ax
34         %endmacro
35         
36         ; Install error handlers
37         %macro SETISR 1
38         SETIDT %1, Isr%1
39         %endmacro
40         
41         %assign i 0
42         %rep 32
43         SETISR i
44         %assign i i+1
45         %endrep
46         
47         ; Install IRQs
48         SETIDT  0xF0, PIT_IRQ
49         SETIDT  0xF1, Irq1
50         SETIDT  0xF2, Irq2
51         SETIDT  0xF3, Irq3
52         SETIDT  0xF4, Irq4
53         SETIDT  0xF5, Irq5
54         SETIDT  0xF6, Irq6
55         SETIDT  0xF7, Irq7
56         SETIDT  0xF8, Irq8
57         SETIDT  0xF9, Irq9
58         SETIDT  0xFA, Irq10
59         SETIDT  0xFB, Irq11
60         SETIDT  0xFC, Irq12
61         SETIDT  0xFD, Irq13
62         SETIDT  0xFE, Irq14
63         SETIDT  0xFF, Irq15
64
65         ; Remap PIC
66         push rdx        ; Save RDX
67         mov dx, 0x20
68         mov al, 0x11
69         out dx, al      ;       Init Command
70         mov dx, 0x21
71         mov al, 0xF0
72         out dx, al      ;       Offset (Start of IDT Range)
73         mov al, 0x04
74         out dx, al      ;       IRQ connected to Slave (00000100b) = IRQ2
75         mov al, 0x01
76         out dx, al      ;       Set Mode
77         mov al, 0x00
78         out dx, al      ;       Set Mode
79         
80         mov dx, 0xA0
81         mov al, 0x11
82         out dx, al      ;       Init Command
83         mov dx, 0xA1
84         mov al, 0xF8
85         out dx, al      ;       Offset (Start of IDT Range)
86         mov al, 0x02
87         out dx, al      ;       IRQ Line connected to master
88         mov al, 0x01
89         out dx, al      ;       Set Mode
90         mov dl, 0x00
91         out dx, al      ;       Set Mode
92         pop rdx
93         
94         
95         ; Install IDT
96         mov rax, gIDTPtr
97         lidt [rax]
98         
99         ; Re-install GDT (in higher address space)
100         mov rax, gGDTPtr
101         mov rcx, gGDT
102         mov QWORD [rax+2], rcx
103         lgdt [rax]
104         
105         ; Start interrupts
106         sti
107
108         ; Set IA32_LSTAR (RIP of handler)
109         mov ecx, 0xC0000082     ; IA32_LSTAR
110         mov eax, SyscallStub - 0xFFFFFFFF00000000
111         mov edx, 0xFFFFFFFF
112         wrmsr
113         ; Set IA32_FMASK (flags mask)
114         mov ecx, 0xC0000084
115         rdmsr
116         mov eax, ~0x202
117         wrmsr
118         ; Set IA32_STAR (Kernel/User CS)
119         mov ecx, 0xC0000081
120         rdmsr
121         mov edx, 0x8 | (0x1B << 16)     ; Kernel CS (and Kernel DS/SS - 8), User CS
122         wrmsr
123         
124         ret
125
126 ; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ), void *Ptr)
127 ; Return Values:
128 ;  0 on Success
129 ; -1 on an invalid IRQ Number
130 ; -2 when no slots are avaliable
131 [global IRQ_AddHandler]
132 IRQ_AddHandler:
133         ; RDI - IRQ Number
134         ; RSI - Callback
135         ; RDX - Ptr
136         
137         ; Check for RDI >= 16
138         cmp rdi, 16
139         jb .numOK
140         xor rax, rax
141         dec rax
142         jmp .ret
143 .numOK:
144
145         ; Get handler base into RAX
146         lea rax, [rdi*4]
147         mov rcx, gaIRQ_Handlers
148         lea rax, [rcx+rax*8]
149         
150         ; Find a free callback slot
151         %rep NUM_IRQ_CALLBACKS
152         mov rcx, [rax]
153         test rcx, rcx
154         jz .assign
155         add rax, 8
156         %endrep
157         ; None found, return -2
158         xor rax, rax
159         dec rax
160         dec rax
161         jmp .ret
162         
163         ; Assign the IRQ Callback
164 .assign:
165         ; A little bit of debug
166         push rdi
167         push rsi
168         push rax
169         push rdx
170         sub rsp, 8
171         mov rcx, rsi    ; IRQ Number
172         mov rdx, rdi    ; Callback
173         mov rsi, csIRQ_Assigned
174         mov rdi, csIRQ_Tag
175         call Log_Debug
176         add rsp, 8
177         pop rdx
178         pop rax
179         pop rsi
180         pop rdi
181
182         ; Assign and return
183         mov [rax], rsi
184         add rax, gaIRQ_DataPtrs - gaIRQ_Handlers
185         mov [rax], rdx
186         xor rax, rax
187
188 .ret:
189         ret
190         
191 [section .rodata]
192 csIRQ_Assigned:
193         db      "IRQ %i .= %p",0
194 csIRQ_Fired:
195         db      "IRQ %i fired",0
196 csIRQ_Tag:
197         db      "IRQ",0
198 [section .text]
199
200 %macro ISR_NOERRNO      1
201 Isr%1:
202         push    QWORD 0
203         push    QWORD %1
204         jmp     ErrorCommon
205 %endmacro
206 %macro ISR_ERRNO        1
207 Isr%1:
208         push    QWORD %1
209         jmp     ErrorCommon
210 %endmacro
211
212 ISR_NOERRNO     0;  0: Divide By Zero Exception
213 ISR_NOERRNO     1;  1: Debug Exception
214 ISR_NOERRNO     2;  2: Non Maskable Interrupt Exception
215 ISR_NOERRNO     3;  3: Int 3 Exception
216 ISR_NOERRNO     4;  4: INTO Exception
217 ISR_NOERRNO     5;  5: Out of Bounds Exception
218 ISR_NOERRNO     6;  6: Invalid Opcode Exception
219 ISR_NOERRNO     7;  7: Coprocessor Not Available Exception
220 ISR_ERRNO       8;  8: Double Fault Exception (With Error Code!)
221 ISR_NOERRNO     9;  9: Coprocessor Segment Overrun Exception
222 ISR_ERRNO       10; 10: Bad TSS Exception (With Error Code!)
223 ISR_ERRNO       11; 11: Segment Not Present Exception (With Error Code!)
224 ISR_ERRNO       12; 12: Stack Fault Exception (With Error Code!)
225 ISR_ERRNO       13; 13: General Protection Fault Exception (With Error Code!)
226 ISR_ERRNO       14; 14: Page Fault Exception (With Error Code!)
227 ISR_NOERRNO     15; 15: Reserved Exception
228 ISR_NOERRNO     16; 16: Floating Point Exception
229 ISR_NOERRNO     17; 17: Alignment Check Exception
230 ISR_NOERRNO     18; 18: Machine Check Exception
231 ISR_NOERRNO     19; 19: Reserved
232 ISR_NOERRNO     20; 20: Reserved
233 ISR_NOERRNO     21; 21: Reserved
234 ISR_NOERRNO     22; 22: Reserved
235 ISR_NOERRNO     23; 23: Reserved
236 ISR_NOERRNO     24; 24: Reserved
237 ISR_NOERRNO     25; 25: Reserved
238 ISR_NOERRNO     26; 26: Reserved
239 ISR_NOERRNO     27; 27: Reserved
240 ISR_NOERRNO     28; 28: Reserved
241 ISR_NOERRNO     29; 29: Reserved
242 ISR_NOERRNO     30; 30: Reserved
243 ISR_NOERRNO     31; 31: Reserved
244
245 [extern Error_Handler]
246 [global ErrorCommon]
247 ErrorCommon:
248         PUSH_GPR
249         push gs
250         push fs
251         ;PUSH_FPU
252         ;PUSH_XMM
253         
254         mov rdi, rsp
255 ;       xchg bx, bx
256         call Error_Handler
257         
258         ;POP_XMM
259         ;POP_FPU
260         pop fs
261         pop gs
262         POP_GPR
263         add rsp, 2*8
264         iretq
265
266 %macro DEFIRQ   1
267 Irq%1:
268         push    0
269         push    %1
270         jmp     IrqCommon
271 %endmacro
272
273 %assign i 0
274 %rep 16
275 DEFIRQ  i
276 %assign i i+1
277 %endrep
278
279 [extern Proc_int_SetIRQIP]
280
281 [global IrqCommon]
282 IrqCommon:
283         PUSH_GPR
284         push gs
285         push fs
286         
287         mov rdi, [rsp+(16+2+2)*8]       ; 2SReg + GPRs + Int/Errcode = RIP
288         call Proc_int_SetIRQIP
289         push rax
290         
291 ;       mov rdi, csIRQ_Fired
292 ;       mov rsi, [rsp+(16+2)*8]
293 ;       call Log
294         
295         mov ebx, [rsp+(1+2+16)*8]       ; Get interrupt number (16 GPRS + 2 SRs)
296         shl ebx, 2      ; *4
297         mov rax, gaIRQ_Handlers
298         lea rbx, [rax+rbx*8]
299         
300         ; Check all callbacks
301         sub rsp, 8      ; Shadow of argument
302         %assign i 0
303         %rep NUM_IRQ_CALLBACKS
304         ; Get callback address
305         mov rax, [rbx]
306         test rax, rax   ; Check if it exists
307         jz .skip.%[i]
308         ; Set RDI to IRQ number
309         mov rdi, [rsp+(16+2+1+1)*8]     ; Get IRQ number
310         mov rsi, [rbx-gaIRQ_Handlers+gaIRQ_DataPtrs]
311         call rax        ; Call
312 .skip.%[i]:
313         add rbx, 8      ; Next!
314         %assign i i+1
315         %endrep
316         add rsp, 8
317         
318         ; ACK
319         mov al, 0x20
320         mov rdi, [rsp+(16+2+1)*8]       ; Get IRQ number
321         cmp rdi, 8
322         jb .skipAckSecondary
323         out 0xA0, al
324 .skipAckSecondary:
325         out 0x20, al
326
327         pop rdi
328         call Proc_int_SetIRQIP
329         
330         pop fs
331         pop gs
332         POP_GPR
333         add rsp, 8*2
334         iretq
335
336 [extern Time_UpdateTimestamp]
337
338 %if USE_MP
339 [global APIC_Timer_IRQ]
340 APIC_Timer_IRQ:
341         PUSH_GPR
342         push gs
343         push fs
344
345         ; TODO: What to do?
346
347         mov eax, DWORD [gpMP_LocalAPIC]
348         mov DWORD [eax+0x0B0], 0
349
350         pop fs
351         pop gs
352         POP_GPR
353         iretq
354 %endif
355
356 [global PIT_IRQ]
357 PIT_IRQ:
358         PUSH_GPR
359         ;PUSH_FPU
360         ;PUSH_XMM
361         
362         call Time_UpdateTimestamp
363
364         %if 0
365 [section .rodata]
366 csUserSS:       db      "User SS: 0x%x",0
367 [section .text]
368         mov rdi, csUserSS
369         mov rsi, [rsp+0x80+0x20]
370         call Log
371         %endif
372
373         ; Send EOI
374         mov al, 0x20
375         out 0x20, al            ; ACK IRQ
376         
377         ;POP_XMM
378         ;POP_FPU
379         POP_GPR
380         iretq
381
382 [extern ci_offsetof_tThread_KernelStack]
383 [extern SyscallHandler]
384 [global SyscallStub]
385 SyscallStub:
386         mov rbp, dr0
387         mov ebx, [rel ci_offsetof_tThread_KernelStack]
388         mov rbp, [rbp+rbx]      ; Get kernel stack
389         xchg rbp, rsp   ; Swap stacks
390
391         push rbp        ; Save User RSP
392         push rcx        ; RIP
393         push r11        ; RFLAGS
394
395         ; RDI
396         ; RSI
397         ; RDX
398         ; R10 (RCX for non syscall)
399         ; R8
400         ; R9
401         sub rsp, (6+2)*8
402         mov [rsp+0x00], rax     ; Number
403 ;       mov [rsp+0x08], rax     ; Errno (output only)
404         mov [rsp+0x10], rdi     ; Arg1
405         mov [rsp+0x18], rsi     ; Arg2
406         mov [rsp+0x20], rdx     ; Arg3
407         mov [rsp+0x28], r10     ; Arg4 (r10 used in place of rcx)
408         mov [rsp+0x30], r8      ; Arg5
409         mov [rsp+0x38], r9      ; Arg6
410
411         mov rdi, rcx    
412         call Proc_int_SetIRQIP
413
414         mov rdi, rsp
415         sub rsp, 8
416         call SyscallHandler
417
418         %if 0
419 [section .rodata]
420 csSyscallReturn:        db      "Syscall Return: 0x%x",0
421 [section .text]
422         mov rdi, csSyscallReturn
423         mov rsi, [rsp+0+8]
424         call Log
425         %endif
426
427         add rsp, 8
428         mov ebx, [rsp+8]        ; Get errno
429         mov rax, [rsp+0]        ; Get return
430         add rsp, (6+2)*8
431
432         pop r11
433         pop rcx
434         pop rsp         ; Change back to user stack
435         ; TODO: Determine if user is 64 or 32 bit
436
437         db 0x48 ; REX, nasm doesn't have a sysretq opcode
438         sysret
439
440 [section .data]
441 gIDT:
442         ; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled)
443         times 256       dd      0x00080000, 0x00000E00, 0, 0
444 gIDTPtr:
445         dw      256*16-1
446         dq      gIDT
447
448 gaIRQ_Handlers:
449         times   16*NUM_IRQ_CALLBACKS    dq      0
450 gaIRQ_DataPtrs:
451         times   16*NUM_IRQ_CALLBACKS    dq      0
452
453 ; vim: ft=nasm

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