2ad44a0c24f1107f0c3008ffc9af22fa510d7d8e
[tpg/acess2.git] / 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         ; Initialise System Calls (SYSCALL/SYSRET)
108         ; Set IA32_EFER.SCE
109         mov ecx, 0xC0000080
110         rdmsr
111         or eax, 1
112         wrmsr
113         ; Set IA32_LSTAR (RIP of handler)
114         mov ecx, 0xC0000082     ; IA32_LSTAR
115         mov eax, SyscallStub - 0xFFFFFFFF00000000
116         mov edx, 0xFFFFFFFF
117         wrmsr
118         ; Set IA32_FMASK (flags mask)
119         mov ecx, 0xC0000084
120         rdmsr
121         mov eax, ~0x202
122         wrmsr
123         ; Set IA32_STAR (Kernel/User CS)
124         mov ecx, 0xC0000081
125         rdmsr
126         mov edx, 0x8 | (0x1B << 16)     ; Kernel CS (and Kernel DS/SS - 8), User CS
127         wrmsr
128         
129         ret
130
131 ; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ), void *Ptr)
132 ; Return Values:
133 ;  0 on Success
134 ; -1 on an invalid IRQ Number
135 ; -2 when no slots are avaliable
136 [global IRQ_AddHandler]
137 IRQ_AddHandler:
138         ; RDI - IRQ Number
139         ; RSI - Callback
140         ; RDX - Ptr
141         
142         ; Check for RDI >= 16
143         cmp rdi, 16
144         jb .numOK
145         xor rax, rax
146         dec rax
147         jmp .ret
148 .numOK:
149
150         ; Get handler base into RAX
151         lea rax, [rdi*4]
152         mov rcx, gaIRQ_Handlers
153         lea rax, [rcx+rax*8]
154         
155         ; Find a free callback slot
156         %rep NUM_IRQ_CALLBACKS
157         mov rcx, [rax]
158         test rcx, rcx
159         jz .assign
160         add rax, 8
161         %endrep
162         ; None found, return -2
163         xor rax, rax
164         dec rax
165         dec rax
166         jmp .ret
167         
168         ; Assign the IRQ Callback
169 .assign:
170         ; A little bit of debug
171         push rdi
172         push rsi
173         push rax
174         push rdx
175         sub rsp, 8
176         mov rcx, rdi    ; IRQ Number
177         mov rdx, rsi    ; Callback
178         mov rsi, rax    ; Pointer
179         mov rdi, csIRQ_Assigned
180         call Log
181         add rsp, 8
182         pop rdx
183         pop rax
184         pop rsi
185         pop rdi
186
187         ; Assign and return
188         mov [rax], rsi
189         add rax, gaIRQ_DataPtrs - gaIRQ_Handlers
190         mov [rax], rdx
191         xor rax, rax
192
193 .ret:
194         ret
195         
196 [section .rodata]
197 csIRQ_Assigned:
198         db      "IRQ %p := %p (IRQ %i)",0
199 csIRQ_Fired:
200         db      "IRQ %i fired",0
201 [section .text]
202
203 %macro ISR_NOERRNO      1
204 Isr%1:
205         push    QWORD 0
206         push    QWORD %1
207         jmp     ErrorCommon
208 %endmacro
209 %macro ISR_ERRNO        1
210 Isr%1:
211         push    QWORD %1
212         jmp     ErrorCommon
213 %endmacro
214
215 ISR_NOERRNO     0;  0: Divide By Zero Exception
216 ISR_NOERRNO     1;  1: Debug Exception
217 ISR_NOERRNO     2;  2: Non Maskable Interrupt Exception
218 ISR_NOERRNO     3;  3: Int 3 Exception
219 ISR_NOERRNO     4;  4: INTO Exception
220 ISR_NOERRNO     5;  5: Out of Bounds Exception
221 ISR_NOERRNO     6;  6: Invalid Opcode Exception
222 ISR_NOERRNO     7;  7: Coprocessor Not Available Exception
223 ISR_ERRNO       8;  8: Double Fault Exception (With Error Code!)
224 ISR_NOERRNO     9;  9: Coprocessor Segment Overrun Exception
225 ISR_ERRNO       10; 10: Bad TSS Exception (With Error Code!)
226 ISR_ERRNO       11; 11: Segment Not Present Exception (With Error Code!)
227 ISR_ERRNO       12; 12: Stack Fault Exception (With Error Code!)
228 ISR_ERRNO       13; 13: General Protection Fault Exception (With Error Code!)
229 ISR_ERRNO       14; 14: Page Fault Exception (With Error Code!)
230 ISR_NOERRNO     15; 15: Reserved Exception
231 ISR_NOERRNO     16; 16: Floating Point Exception
232 ISR_NOERRNO     17; 17: Alignment Check Exception
233 ISR_NOERRNO     18; 18: Machine Check Exception
234 ISR_NOERRNO     19; 19: Reserved
235 ISR_NOERRNO     20; 20: Reserved
236 ISR_NOERRNO     21; 21: Reserved
237 ISR_NOERRNO     22; 22: Reserved
238 ISR_NOERRNO     23; 23: Reserved
239 ISR_NOERRNO     24; 24: Reserved
240 ISR_NOERRNO     25; 25: Reserved
241 ISR_NOERRNO     26; 26: Reserved
242 ISR_NOERRNO     27; 27: Reserved
243 ISR_NOERRNO     28; 28: Reserved
244 ISR_NOERRNO     29; 29: Reserved
245 ISR_NOERRNO     30; 30: Reserved
246 ISR_NOERRNO     31; 31: Reserved
247
248 [extern Error_Handler]
249 [global ErrorCommon]
250 ErrorCommon:
251         PUSH_GPR
252         push gs
253         push fs
254         ;PUSH_FPU
255         ;PUSH_XMM
256         
257         mov rdi, rsp
258 ;       xchg bx, bx
259         call Error_Handler
260         
261         ;POP_XMM
262         ;POP_FPU
263         pop fs
264         pop gs
265         POP_GPR
266         add rsp, 2*8
267         iretq
268
269 %macro DEFIRQ   1
270 Irq%1:
271         push    0
272         push    %1
273         jmp     IrqCommon
274 %endmacro
275
276 %assign i 0
277 %rep 16
278 DEFIRQ  i
279 %assign i i+1
280 %endrep
281
282 [global IrqCommon]
283 IrqCommon:
284         PUSH_GPR
285         push gs
286         push fs
287
288 ;       mov rdi, csIRQ_Fired
289 ;       mov rsi, [rsp+(16+2)*8]
290 ;       call Log
291         
292         mov ebx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs)
293         shl ebx, 2      ; *4
294         mov rax, gaIRQ_Handlers
295         lea rbx, [rax+rbx*8]
296         
297         ; Check all callbacks
298         sub rsp, 8      ; Shadow of argument
299         %assign i 0
300         %rep NUM_IRQ_CALLBACKS
301         ; Get callback address
302         mov rax, [rbx]
303         test rax, rax   ; Check if it exists
304         jz .skip.%[i]
305         ; Set RDI to IRQ number
306         mov rdi, [rsp+(16+2+1)*8]       ; Get IRQ number
307         mov rsi, [rbx-gaIRQ_Handlers+gaIRQ_DataPtrs]
308         call rax        ; Call
309 .skip.%[i]:
310         add rbx, 8      ; Next!
311         %assign i i+1
312         %endrep
313         add rsp, 8
314         
315         ; ACK
316         mov al, 0x20
317         mov rdi, [rsp+(16+2)*8] ; Get IRQ number
318         cmp rdi, 8
319         jb .skipAckSecondary
320         out 0xA0, al
321 .skipAckSecondary:
322         out 0x20, al
323         
324         pop fs
325         pop gs
326         POP_GPR
327         add rsp, 8*2
328         iretq
329
330 [extern Time_UpdateTimestamp]
331
332 %if USE_MP
333 [global APIC_Timer_IRQ]
334 APIC_Timer_IRQ:
335         PUSH_GPR
336         push gs
337         push fs
338
339         ; TODO: What to do?
340
341         mov eax, DWORD [gpMP_LocalAPIC]
342         mov DWORD [eax+0x0B0], 0
343
344         pop fs
345         pop gs
346         POP_GPR
347         iretq
348 %endif
349
350 [global PIT_IRQ]
351 PIT_IRQ:
352         PUSH_GPR
353         ;PUSH_FPU
354         ;PUSH_XMM
355         
356         call Time_UpdateTimestamp
357
358         %if 0
359 [section .rodata]
360 csUserSS:       db      "User SS: 0x%x",0
361 [section .text]
362         mov rdi, csUserSS
363         mov rsi, [rsp+0x80+0x20]
364         call Log
365         %endif
366
367         ; Send EOI
368         mov al, 0x20
369         out 0x20, al            ; ACK IRQ
370         
371         ;POP_XMM
372         ;POP_FPU
373         POP_GPR
374         iretq
375
376 [extern ci_offsetof_tThread_KernelStack]
377 [extern SyscallHandler]
378 [global SyscallStub]
379 SyscallStub:
380         mov rbp, dr0
381         mov ebx, [rel ci_offsetof_tThread_KernelStack]
382         mov rbp, [rbp+rbx]      ; Get kernel stack
383         xchg rbp, rsp   ; Swap stacks
384
385         push rbp        ; Save User RSP
386         push rcx        ; RIP
387         push r11        ; RFLAGS
388
389         ; RDI
390         ; RSI
391         ; RDX
392         ; R10 (RCX for non syscall)
393         ; R8
394         ; R9
395         sub rsp, (6+2)*8
396         mov [rsp+0x00], rax     ; Number
397 ;       mov [rsp+0x08], rax     ; Errno (output only)
398         mov [rsp+0x10], rdi     ; Arg1
399         mov [rsp+0x18], rsi     ; Arg2
400         mov [rsp+0x20], rdx     ; Arg3
401         mov [rsp+0x28], r10     ; Arg4
402         mov [rsp+0x30], r8      ; Arg5
403         mov [rsp+0x38], r9      ; Arg6
404         
405         mov rdi, rsp
406         sub rsp, 8
407         call SyscallHandler
408
409         %if 0
410 [section .rodata]
411 csSyscallReturn:        db      "Syscall Return: 0x%x",0
412 [section .text]
413         mov rdi, csSyscallReturn
414         mov rsi, [rsp+0+8]
415         call Log
416         %endif
417
418         add rsp, 8
419         mov ebx, [rsp+8]        ; Get errno
420         mov rax, [rsp+0]        ; Get return
421         add rsp, (6+2)*8
422
423         pop r11
424         pop rcx
425         pop rsp         ; Change back to user stack
426         ; TODO: Determine if user is 64 or 32 bit
427
428         db 0x48 ; REX, nasm doesn't have a sysretq opcode
429         sysret
430
431 [section .data]
432 gIDT:
433         ; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled)
434         times 256       dd      0x00080000, 0x00000E00, 0, 0
435 gIDTPtr:
436         dw      256*16-1
437         dq      gIDT
438
439 gaIRQ_Handlers:
440         times   16*NUM_IRQ_CALLBACKS    dq      0
441 gaIRQ_DataPtrs:
442         times   16*NUM_IRQ_CALLBACKS    dq      0
443
444 ; vim: ft=nasm

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