10 %define NUM_IRQ_CALLBACKS 4
12 MM_LOCALAPIC equ 0xFFFFFD0000000000
56 ; Save to make following instructions smaller
59 ; Set an IDT entry to a callback
62 mov WORD [rdi + %1*16], ax
64 mov WORD [rdi + %1*16 + 6], ax
66 mov DWORD [rdi + %1*16 + 8], eax
68 mov ax, WORD [rdi + %1*16 + 4]
70 mov WORD [rdi + %1*16 + 4], ax
73 ; Install error handlers
85 SETIDT 0xF0, SchedulerIRQ
106 out dx, al ; Init Command
109 out dx, al ; Offset (Start of IDT Range)
111 out dx, al ; IRQ connected to Slave (00000100b) = IRQ2
113 out dx, al ; Set Mode
115 out dx, al ; Set Mode
119 out dx, al ; Init Command
122 out dx, al ; Offset (Start of IDT Range)
124 out dx, al ; IRQ Line connected to master
126 out dx, al ; Set Mode
128 out dx, al ; Set Mode
136 ; Re-install GDT (in higher address space)
139 mov QWORD [rax+2], rcx
145 ; Initialise System Calls (SYSCALL/SYSRET)
151 ; Set IA32_LSTAR (RIP of handler)
152 mov ecx, 0xC0000082 ; IA32_LSTAR
153 mov eax, SyscallStub - 0xFFFFFFFF00000000
156 ; Set IA32_FMASK (flags mask)
161 ; Set IA32_STAR (Kernel/User CS)
164 mov edx, 0x8 | (0x18 << 16) ; Kernel CS (and Kernel DS/SS - 8), User CS
169 ; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ))
172 ; -1 on an invalid IRQ Number
173 ; -2 when no slots are avaliable
174 [global IRQ_AddHandler]
179 ; Check for RDI >= 16
187 ; Get handler base into RAX
189 mov rcx, gaIRQ_Handlers
192 ; Find a free callback slot
193 %rep NUM_IRQ_CALLBACKS
199 ; None found, return -2
205 ; Assign the IRQ Callback
207 ; A little bit of debug
212 mov rcx, rdi ; IRQ Number
213 mov rdx, rsi ; Callback
214 mov rsi, rax ; Pointer
215 mov rdi, csIRQ_Assigned
231 db "IRQ %p := %p (IRQ %i)",0
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
279 [extern Error_Handler]
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)
322 mov rax, gaIRQ_Handlers
325 ; Check all callbacks
326 sub rsp, 8 ; Shadow of argument
328 %rep NUM_IRQ_CALLBACKS
329 ; Get callback address
331 test rax, rax ; Check if it exists
333 ; Set RDI to IRQ number
334 mov rdi, [rsp+(16+2+1)*8] ; Get IRQ number
344 mov rdi, [rsp+16*8] ; Get IRQ number
360 [extern Proc_Scheduler]
361 [global SchedulerIRQ]
363 ; NOTE: Proc_Scheduler makes assumptions about the stack state when called
374 ; Save Thread Pointer
383 ; Restore Thread Pointer
387 ; Send EOI (To either the APIC or the PIC)
394 out 0x20, al ; ACK IRQ
399 mov eax, DWORD [gpMP_LocalAPIC]
400 mov DWORD [eax+0x0B0], 0
409 add rsp, 2*8 ; Dummy error code and IRQ num
412 [extern ci_offsetof_tThread_KernelStack]
413 [extern SyscallHandler]
417 mov ebx, [rel ci_offsetof_tThread_KernelStack]
418 mov rbp, [rbp+rbx] ; Get kernel stack
419 xchg rbp, rsp ; Swap stacks
421 push rbp ; Save User RSP
428 ; R10 (RCX for non syscall)
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
445 mov ebx, [rsp+8] ; Get errno
446 mov rax, [rsp+0] ; Get return
451 pop rsp ; Change back to user stack
456 ; 64-bit Interrupt Gate, CS = 0x8, IST0 (Disabled)
457 times 256 dd 0x00080000, 0x00000E00, 0, 0
463 times 16*NUM_IRQ_CALLBACKS dq 0