4 %include "arch/x86_64/include/common.inc.asm"
12 %define NUM_IRQ_CALLBACKS 4
14 MM_LOCALAPIC equ 0xFFFFFD0000000000
19 ; Save to make following instructions smaller
22 ; Set an IDT entry to a callback
25 mov WORD [rdi + %1*16], ax
27 mov WORD [rdi + %1*16 + 6], ax
29 mov DWORD [rdi + %1*16 + 8], eax
31 mov ax, WORD [rdi + %1*16 + 4]
33 mov WORD [rdi + %1*16 + 4], ax
36 ; Install error handlers
69 out dx, al ; Init Command
72 out dx, al ; Offset (Start of IDT Range)
74 out dx, al ; IRQ connected to Slave (00000100b) = IRQ2
82 out dx, al ; Init Command
85 out dx, al ; Offset (Start of IDT Range)
87 out dx, al ; IRQ Line connected to master
99 ; Re-install GDT (in higher address space)
102 mov QWORD [rax+2], rcx
108 ; Set IA32_LSTAR (RIP of handler)
109 mov ecx, 0xC0000082 ; IA32_LSTAR
110 mov eax, SyscallStub - 0xFFFFFFFF00000000
113 ; Set IA32_FMASK (flags mask)
118 ; Set IA32_STAR (Kernel/User CS)
121 mov edx, 0x8 | (0x1B << 16) ; Kernel CS (and Kernel DS/SS - 8), User CS
126 ; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ), void *Ptr)
129 ; -1 on an invalid IRQ Number
130 ; -2 when no slots are avaliable
131 [global IRQ_AddHandler]
137 ; Check for RDI >= 16
145 ; Get handler base into RAX
147 mov rcx, gaIRQ_Handlers
150 ; Find a free callback slot
151 %rep NUM_IRQ_CALLBACKS
157 ; None found, return -2
163 ; Assign the IRQ Callback
165 ; A little bit of debug
171 mov rcx, rsi ; IRQ Number
172 mov rdx, rdi ; Callback
173 mov rsi, csIRQ_Assigned
184 add rax, gaIRQ_DataPtrs - gaIRQ_Handlers
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
245 [extern Error_Handler]
279 [extern Proc_int_SetIRQIP]
287 mov rdi, [rsp+(16+2+2)*8] ; 2SReg + GPRs + Int/Errcode = RIP
288 call Proc_int_SetIRQIP
291 ; mov rdi, csIRQ_Fired
292 ; mov rsi, [rsp+(16+2)*8]
295 mov ebx, [rsp+(1+2+16)*8] ; Get interrupt number (16 GPRS + 2 SRs)
297 mov rax, gaIRQ_Handlers
300 ; Check all callbacks
301 sub rsp, 8 ; Shadow of argument
303 %rep NUM_IRQ_CALLBACKS
304 ; Get callback address
306 test rax, rax ; Check if it exists
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]
320 mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
328 call Proc_int_SetIRQIP
336 [extern Time_UpdateTimestamp]
339 [global APIC_Timer_IRQ]
347 mov eax, DWORD [gpMP_LocalAPIC]
348 mov DWORD [eax+0x0B0], 0
362 call Time_UpdateTimestamp
366 csUserSS: db "User SS: 0x%x",0
369 mov rsi, [rsp+0x80+0x20]
375 out 0x20, al ; ACK IRQ
382 [extern ci_offsetof_tThread_KernelStack]
383 [extern SyscallHandler]
387 mov ebx, [rel ci_offsetof_tThread_KernelStack]
388 mov rbp, [rbp+rbx] ; Get kernel stack
389 xchg rbp, rsp ; Swap stacks
391 push rbp ; Save User RSP
398 ; R10 (RCX for non syscall)
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
408 mov [rsp+0x30], r8 ; Arg5
409 mov [rsp+0x38], r9 ; Arg6
412 call Proc_int_SetIRQIP
420 csSyscallReturn: db "Syscall Return: 0x%x",0
422 mov rdi, csSyscallReturn
428 mov ebx, [rsp+8] ; Get errno
429 mov rax, [rsp+0] ; Get return
434 pop rsp ; Change back to user stack
435 ; TODO: Determine if user is 64 or 32 bit
437 db 0x48 ; REX, nasm doesn't have a sysretq opcode
442 ; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled)
443 times 256 dd 0x00080000, 0x00000E00, 0, 0
449 times 16*NUM_IRQ_CALLBACKS dq 0
451 times 16*NUM_IRQ_CALLBACKS dq 0