Kernel - x86_64 booting again (with some hackery)
[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 [global IrqCommon]
280 IrqCommon:
281         PUSH_GPR
282         push gs
283         push fs
284
285 ;       mov rdi, csIRQ_Fired
286 ;       mov rsi, [rsp+(16+2)*8]
287 ;       call Log
288         
289         mov ebx, [rsp+(16+2)*8] ; Get interrupt number (16 GPRS + 2 SRs)
290         shl ebx, 2      ; *4
291         mov rax, gaIRQ_Handlers
292         lea rbx, [rax+rbx*8]
293         
294         ; Check all callbacks
295         sub rsp, 8      ; Shadow of argument
296         %assign i 0
297         %rep NUM_IRQ_CALLBACKS
298         ; Get callback address
299         mov rax, [rbx]
300         test rax, rax   ; Check if it exists
301         jz .skip.%[i]
302         ; Set RDI to IRQ number
303         mov rdi, [rsp+(16+2+1)*8]       ; Get IRQ number
304         mov rsi, [rbx-gaIRQ_Handlers+gaIRQ_DataPtrs]
305         call rax        ; Call
306 .skip.%[i]:
307         add rbx, 8      ; Next!
308         %assign i i+1
309         %endrep
310         add rsp, 8
311         
312         ; ACK
313         mov al, 0x20
314         mov rdi, [rsp+(16+2)*8] ; Get IRQ number
315         cmp rdi, 8
316         jb .skipAckSecondary
317         out 0xA0, al
318 .skipAckSecondary:
319         out 0x20, al
320         
321         pop fs
322         pop gs
323         POP_GPR
324         add rsp, 8*2
325         iretq
326
327 [extern Time_UpdateTimestamp]
328
329 %if USE_MP
330 [global APIC_Timer_IRQ]
331 APIC_Timer_IRQ:
332         PUSH_GPR
333         push gs
334         push fs
335
336         ; TODO: What to do?
337
338         mov eax, DWORD [gpMP_LocalAPIC]
339         mov DWORD [eax+0x0B0], 0
340
341         pop fs
342         pop gs
343         POP_GPR
344         iretq
345 %endif
346
347 [global PIT_IRQ]
348 PIT_IRQ:
349         PUSH_GPR
350         ;PUSH_FPU
351         ;PUSH_XMM
352         
353         call Time_UpdateTimestamp
354
355         %if 0
356 [section .rodata]
357 csUserSS:       db      "User SS: 0x%x",0
358 [section .text]
359         mov rdi, csUserSS
360         mov rsi, [rsp+0x80+0x20]
361         call Log
362         %endif
363
364         ; Send EOI
365         mov al, 0x20
366         out 0x20, al            ; ACK IRQ
367         
368         ;POP_XMM
369         ;POP_FPU
370         POP_GPR
371         iretq
372
373 [extern ci_offsetof_tThread_KernelStack]
374 [extern SyscallHandler]
375 [global SyscallStub]
376 SyscallStub:
377         mov rbp, dr0
378         mov ebx, [rel ci_offsetof_tThread_KernelStack]
379         mov rbp, [rbp+rbx]      ; Get kernel stack
380         xchg rbp, rsp   ; Swap stacks
381
382         push rbp        ; Save User RSP
383         push rcx        ; RIP
384         push r11        ; RFLAGS
385
386         ; RDI
387         ; RSI
388         ; RDX
389         ; R10 (RCX for non syscall)
390         ; R8
391         ; R9
392         sub rsp, (6+2)*8
393         mov [rsp+0x00], rax     ; Number
394 ;       mov [rsp+0x08], rax     ; Errno (output only)
395         mov [rsp+0x10], rdi     ; Arg1
396         mov [rsp+0x18], rsi     ; Arg2
397         mov [rsp+0x20], rdx     ; Arg3
398         mov [rsp+0x28], r10     ; Arg4
399         mov [rsp+0x30], r8      ; Arg5
400         mov [rsp+0x38], r9      ; Arg6
401         
402         mov rdi, rsp
403         sub rsp, 8
404         call SyscallHandler
405
406         %if 0
407 [section .rodata]
408 csSyscallReturn:        db      "Syscall Return: 0x%x",0
409 [section .text]
410         mov rdi, csSyscallReturn
411         mov rsi, [rsp+0+8]
412         call Log
413         %endif
414
415         add rsp, 8
416         mov ebx, [rsp+8]        ; Get errno
417         mov rax, [rsp+0]        ; Get return
418         add rsp, (6+2)*8
419
420         pop r11
421         pop rcx
422         pop rsp         ; Change back to user stack
423         ; TODO: Determine if user is 64 or 32 bit
424
425         db 0x48 ; REX, nasm doesn't have a sysretq opcode
426         sysret
427
428 [section .data]
429 gIDT:
430         ; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled)
431         times 256       dd      0x00080000, 0x00000E00, 0, 0
432 gIDTPtr:
433         dw      256*16-1
434         dq      gIDT
435
436 gaIRQ_Handlers:
437         times   16*NUM_IRQ_CALLBACKS    dq      0
438 gaIRQ_DataPtrs:
439         times   16*NUM_IRQ_CALLBACKS    dq      0
440
441 ; vim: ft=nasm

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