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

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