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

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