3 #include <aros/debug.h>
8 #include <asm/segments.h>
9 #include <aros/libcall.h>
10 #include <aros/asmcall.h>
11 #include <exec/execbase.h>
12 #include <hardware/intbits.h>
14 #include <proto/exec.h>
16 #include "kernel_intern.h"
18 static void core_XTPIC_DisableIRQ(uint8_t irqnum
);
19 static void core_XTPIC_EnableIRQ(uint8_t irqnum
);
21 AROS_LH4(void *, KrnAddIRQHandler
,
22 AROS_LHA(uint8_t, irq
, D0
),
23 AROS_LHA(void *, handler
, A0
),
24 AROS_LHA(void *, handlerData
, A1
),
25 AROS_LHA(void *, handlerData2
, A2
),
26 struct KernelBase
*, KernelBase
, 7, Kernel
)
30 struct ExecBase
*SysBase
= TLS_GET(SysBase
);
31 struct IntrNode
*handle
= NULL
;
32 D(bug("[Kernel] KrnAddIRQHandler(%02x, %012p, %012p, %012p):\n", irq
, handler
, handlerData
, handlerData2
));
34 if (irq
>=0 && irq
<= 0xff)
37 handle
= AllocVecPooled(KernelBase
->kb_MemPool
, sizeof(struct IntrNode
));
39 #warning TODO: Add IP range checking
41 D(bug("[Kernel] handle=%012p\n", handle
));
45 handle
->in_Handler
= handler
;
46 handle
->in_HandlerData
= handlerData
;
47 handle
->in_HandlerData2
= handlerData2
;
50 ADDHEAD(&KernelBase
->kb_Intr
[irq
], &handle
->in_Node
);
53 if (KernelBase
->kb_Intr
[irq
].lh_Type
== KBL_XTPIC
)
54 core_XTPIC_EnableIRQ(irq
);
62 AROS_LH1(void, KrnRemIRQHandler
,
63 AROS_LHA(void *, handle
, A0
),
64 struct KernelBase
*, KernelBase
, 8, Kernel
)
68 struct IntrNode
*h
= handle
;
74 FreeVecPooled(KernelBase
->kb_MemPool
, h
);
79 AROS_LH0I(void, KrnCli
,
80 struct KernelBase
*, KernelBase
, 9, Kernel
)
89 AROS_LH0I(void, KrnSti
,
90 struct KernelBase
*, KernelBase
, 10, Kernel
)
100 static struct int_gate_64bit IGATES
[256] __attribute__((used
,aligned(256)));
103 uint16_t size
__attribute__((packed
));
104 uint64_t base
__attribute__((packed
));
105 } IDT_sel
= {sizeof(IGATES
)-1, (uint64_t)IGATES
};
108 #define STR(x) STR_(x)
110 #define IRQ_NAME_(nr) nr##_intr(void)
111 #define IRQ_NAME(nr) IRQ_NAME_(IRQ##nr)
113 #define BUILD_IRQ(nr) \
115 asm(".balign 8 ,0x90\n\t" \
116 ".globl IRQ" STR(nr) "_intr\n\t" \
117 ".type IRQ" STR(nr) "_intr,@function\n" \
118 "IRQ" STR(nr) "_intr: pushq $0; pushq $" #nr "\n\t" \
119 "jmp core_EnterInterrupt\n\t" \
120 ".size IRQ" STR(nr) "_intr, . - IRQ" STR(nr) "_intr" \
123 #define BUILD_IRQ_ERR(nr) \
125 asm(".balign 8 ,0x90\n\t" \
126 ".globl IRQ" STR(nr) "_intr\n\t" \
127 ".type IRQ" STR(nr) "_intr,@function\n" \
128 "IRQ" STR(nr) "_intr: pushq $" #nr "\n\t" \
129 "jmp core_EnterInterrupt\n\t" \
130 ".size IRQ" STR(nr) "_intr, . - IRQ" STR(nr) "_intr" \
133 BUILD_IRQ(0x00) // Divide-By-Zero Exception
134 BUILD_IRQ(0x01) // Debug Exception
135 BUILD_IRQ(0x02) // NMI Exception
136 BUILD_IRQ(0x03) // Breakpoint Exception
137 BUILD_IRQ(0x04) // Overflow Exception
138 BUILD_IRQ(0x05) // Bound-Range Exception
139 BUILD_IRQ(0x06) // Invalid-Opcode Exception
140 BUILD_IRQ(0x07) // Device-Not-Available Exception
141 BUILD_IRQ_ERR(0x08) // Double-Fault Exception
142 BUILD_IRQ(0x09) // Unused (used to be Coprocesor-Segment-Overrun)
143 BUILD_IRQ_ERR(0x0a) // Invalid-TSS Exception
144 BUILD_IRQ_ERR(0x0b) // Segment-Not-Present Exception
145 BUILD_IRQ_ERR(0x0c) // Stack Exception
146 BUILD_IRQ_ERR(0x0d) // General-Protection Exception
147 BUILD_IRQ_ERR(0x0e) // Page-Fault Exception
148 BUILD_IRQ(0x0f) // Reserved
149 BUILD_IRQ(0x10) // Floating-Point Exception
150 BUILD_IRQ_ERR(0x11) // Alignment-Check Exception
151 BUILD_IRQ(0x12) // Machine-Check Exception
152 BUILD_IRQ(0x13) // SIMD-Floating-Point Exception
153 BUILD_IRQ(0x14) BUILD_IRQ(0x15) BUILD_IRQ(0x16) BUILD_IRQ(0x17)
154 BUILD_IRQ(0x18) BUILD_IRQ(0x19) BUILD_IRQ(0x1a) BUILD_IRQ(0x1b)
155 BUILD_IRQ(0x1c) BUILD_IRQ(0x1d) BUILD_IRQ(0x1e) BUILD_IRQ(0x1f)
157 #define B(x,y) BUILD_IRQ(x##y)
159 B(x,0) B(x,1) B(x,2) B(x,3) B(x,4) B(x,5) B(x,6) B(x,7) \
160 B(x,8) B(x,9) B(x,a) B(x,b) B(x,c) B(x,d) B(x,e) B(x,f)
164 BUILD_IRQ(0xfe) // APIC timer
167 "pushq %rax; pushq %rbp; pushq %rbx; pushq %rdi; pushq %rsi; pushq %rdx;" \
168 "pushq %rcx; pushq %r8; pushq %r9; pushq %r10; pushq %r11; pushq %r12;" \
169 "pushq %r13; pushq %r14; pushq %r15; mov %ds,%eax; pushq %rax;"
171 #define RESTORE_REGS \
172 "popq %rax; mov %ax,%ds; mov %ax,%es; popq %r15; popq %r14; popq %r13;" \
173 "popq %r12; popq %r11; popq %r10; popq %r9; popq %r8; popq %rcx;" \
174 "popq %rdx; popq %rsi; popq %rdi; popq %rbx; popq %rbp; popq %rax"
177 " .balign 32,0x90 \n"
178 " .globl core_EnterInterrupt \n"
179 " .type core_EnterInterrupt,@function \n"
180 "core_EnterInterrupt: \n\t" SAVE_REGS
"\n"
181 " movl $" STR(KERNEL_DS
) ",%eax \n"
185 " call core_IRQHandle \n"
187 " jmp core_ExitInterrupt \n"
188 " .size core_EnterInterrupt, .-core_EnterInterrupt"
192 " .balign 32,0x90 \n"
193 " .globl core_LeaveInterrupt \n"
194 " .type core_LeaveInterrupt,@function \n"
195 "core_LeaveInterrupt: movq %rdi,%rsp \n\t" RESTORE_REGS
"\n"
198 " .size core_LeaveInterrupt, .-core_LeaveInterrupt"
202 (const void (*)(void))IRQ##x##y##_intr
204 #define IRQLIST_16(x) \
205 IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
206 IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
207 IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
208 IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
210 const void __attribute__((section(".text"))) (*interrupt
[256])(void) = {
211 IRQLIST_16(0x0), IRQLIST_16(0x1), IRQLIST_16(0x2)
218 rkprintf("[Kernel] Setting all interrupt handlers to default value\n");
220 for (i
=0; i
< 256; i
++)
223 off
= (uintptr_t)interrupt
[i
];
225 off
= (uintptr_t)&IRQ0x80_intr
;
227 off
= (uintptr_t)&IRQ0xfe_intr
;
229 off
= (uintptr_t)&core_DefaultIRETQ
;
231 IGATES
[i
].offset_low
= off
& 0xffff;
232 IGATES
[i
].offset_mid
= (off
>> 16) & 0xffff;
233 IGATES
[i
].offset_high
= (off
>> 32) & 0xffffffff;
234 IGATES
[i
].type
= 0x0e;
237 IGATES
[i
].selector
= KERNEL_CS
;
241 asm volatile ("lidt %0"::"m"(IDT_sel
));
245 void core_Cause(struct ExecBase
*SysBase
)
247 struct IntVector
*iv
= &SysBase
->IntVects
[INTB_SOFTINT
];
249 /* If the SoftInt vector in SysBase is set, call it. It will do the rest for us */
252 AROS_UFC5(void, iv
->iv_Code
,
253 AROS_UFCA(ULONG
, 0, D1
),
254 AROS_UFCA(ULONG
, 0, A0
),
255 AROS_UFCA(APTR
, 0, A1
),
256 AROS_UFCA(APTR
, iv
->iv_Code
, A5
),
257 AROS_UFCA(struct ExecBase
*, SysBase
, A6
)
262 static void core_APIC_AckIntr(uint8_t intnum
)
264 struct KernelBase
*KernelBase
= TLS_GET(KernelBase
);
265 asm volatile ("movl %0,(%1)"::"r"(0),"r"(KernelBase
->kb_APICBase
+ 0xb0));
268 static void core_XTPIC_DisableIRQ(uint8_t irqnum
)
270 struct KernelBase
*KernelBase
= TLS_GET(KernelBase
);
272 KernelBase
->kb_XTPIC_Mask
|= 1 << irqnum
;
276 outb((KernelBase
->kb_XTPIC_Mask
>> 8) & 0xff, 0xA1);
280 outb(KernelBase
->kb_XTPIC_Mask
& 0xff, 0x21);
284 static void core_XTPIC_EnableIRQ(uint8_t irqnum
)
286 struct KernelBase
*KernelBase
= TLS_GET(KernelBase
);
288 KernelBase
->kb_XTPIC_Mask
&= ~(1 << irqnum
);
292 outb((KernelBase
->kb_XTPIC_Mask
>> 8) & 0xff, 0xA1);
296 outb(KernelBase
->kb_XTPIC_Mask
& 0xff, 0x21);
300 static void core_XTPIC_AckIntr(uint8_t intnum
)
302 struct KernelBase
*KernelBase
= TLS_GET(KernelBase
);
304 KernelBase
->kb_XTPIC_Mask
|= 1 << intnum
;
308 outb((KernelBase
->kb_XTPIC_Mask
>> 8) & 0xff, 0xA1);
314 outb(KernelBase
->kb_XTPIC_Mask
& 0xff, 0x21);
319 void core_IRQHandle(regs_t regs
)
321 struct ExecBase
*SysBase
= TLS_GET(SysBase
); // *(struct ExecBase **)4;
322 struct KernelBase
*KernelBase
= TLS_GET(KernelBase
);
323 struct Task
*t
= NULL
;
327 t
= SysBase
->ThisTask
;
329 if ((regs
.irq_number
< 0x20) && regs
.irq_number
!= 0x0e)
330 rkprintf("IRQ %02x:", regs
.irq_number
);
332 if (regs
.irq_number
== 0x03) /* Debug */
334 rkprintf("[Kernel] INT3 debug fault!\n");
336 rkprintf("[Kernel] stack=%04x:%012x rflags=%016x ip=%04x:%012x err=%08x\n",
337 regs
.return_ss
, regs
.return_rsp
, regs
.return_rflags
,
338 regs
.return_cs
, regs
.return_rip
, regs
.error_code
);
340 rkprintf("[Kernel] rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", regs
.rax
, regs
.rbx
, regs
.rcx
, regs
.rdx
);
341 rkprintf("[Kernel] rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n", regs
.rsi
, regs
.rdi
, regs
.rbp
, regs
.return_rsp
);
342 rkprintf("[Kernel] r08=%016lx r09=%016lx r10=%016lx r11=%016lx\n", regs
.r8
, regs
.r9
, regs
.r10
, regs
.r11
);
343 rkprintf("[Kernel] r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", regs
.r12
, regs
.r13
, regs
.r14
, regs
.r15
);
345 rkprintf("[Kenrel] Stack:\n");
347 uint64_t *ptr
= (void*)regs
.return_rsp
;
348 for (i
=0; i
< 10; i
++)
350 rkprintf("[Kernel] %02x: %016p\n", i
*8, ptr
[i
]);
353 else if (regs
.irq_number
== 0x06) /* GPF */
355 rkprintf("[Kernel] UNDEFINED INSTRUCTION!\n");
359 rkprintf("[Kernel] %s %p '%s'\n",
360 t
->tc_Node
.ln_Type
== NT_TASK
?"task":"process", t
, t
->tc_Node
.ln_Name
);
363 rkprintf("[Kernel] stack=%04x:%012x rflags=%016x ip=%04x:%012x err=%08x\n",
364 regs
.return_ss
, regs
.return_rsp
, regs
.return_rflags
,
365 regs
.return_cs
, regs
.return_rip
, regs
.error_code
);
367 rkprintf("[Kernel] rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", regs
.rax
, regs
.rbx
, regs
.rcx
, regs
.rdx
);
368 rkprintf("[Kernel] rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n", regs
.rsi
, regs
.rdi
, regs
.rbp
, regs
.return_rsp
);
369 rkprintf("[Kernel] r08=%016lx r09=%016lx r10=%016lx r11=%016lx\n", regs
.r8
, regs
.r9
, regs
.r10
, regs
.r11
);
370 rkprintf("[Kernel] r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", regs
.r12
, regs
.r13
, regs
.r14
, regs
.r15
);
374 uint8_t *ptr
= (uint8_t *)regs
.return_rip
;
376 rkprintf("[Kernel] ");
378 for (i
=0; i
< 16; i
++)
379 rkprintf("%02x ", ptr
[i
]);
383 else if (regs
.irq_number
== 0x07) /* GPF */
385 rkprintf("[Kernel] Device Not Available!\n");
389 rkprintf("[Kernel] %s %p '%s'\n",
390 t
->tc_Node
.ln_Type
== NT_TASK
?"task":"process", t
, t
->tc_Node
.ln_Name
);
393 rkprintf("[Kernel] stack=%04x:%012x rflags=%016x ip=%04x:%012x err=%08x\n",
394 regs
.return_ss
, regs
.return_rsp
, regs
.return_rflags
,
395 regs
.return_cs
, regs
.return_rip
, regs
.error_code
);
397 rkprintf("[Kernel] rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", regs
.rax
, regs
.rbx
, regs
.rcx
, regs
.rdx
);
398 rkprintf("[Kernel] rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n", regs
.rsi
, regs
.rdi
, regs
.rbp
, regs
.return_rsp
);
399 rkprintf("[Kernel] r08=%016lx r09=%016lx r10=%016lx r11=%016lx\n", regs
.r8
, regs
.r9
, regs
.r10
, regs
.r11
);
400 rkprintf("[Kernel] r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", regs
.r12
, regs
.r13
, regs
.r14
, regs
.r15
);
403 else if (regs
.irq_number
== 0x0D) /* GPF */
405 rkprintf("[Kernel] GENERAL PROTECTION FAULT!\n");
409 rkprintf("[Kernel] %s %p '%s'\n",
410 t
->tc_Node
.ln_Type
== NT_TASK
?"task":"process", t
, t
->tc_Node
.ln_Name
);
413 rkprintf("[Kernel] stack=%04x:%012x rflags=%016x ip=%04x:%012x err=%08x\n",
414 regs
.return_ss
, regs
.return_rsp
, regs
.return_rflags
,
415 regs
.return_cs
, regs
.return_rip
, regs
.error_code
);
417 rkprintf("[Kernel] rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", regs
.rax
, regs
.rbx
, regs
.rcx
, regs
.rdx
);
418 rkprintf("[Kernel] rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n", regs
.rsi
, regs
.rdi
, regs
.rbp
, regs
.return_rsp
);
419 rkprintf("[Kernel] r08=%016lx r09=%016lx r10=%016lx r11=%016lx\n", regs
.r8
, regs
.r9
, regs
.r10
, regs
.r11
);
420 rkprintf("[Kernel] r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", regs
.r12
, regs
.r13
, regs
.r14
, regs
.r15
);
421 rkprintf("[Kernel] *rsp=%016lx\n", *(uint64_t *)regs
.return_rsp
);
424 else if (regs
.irq_number
== 0x0e) /* Page fault */
426 void *ptr
= rdcr(cr2
);
427 unsigned char *ip
= regs
.return_rip
;
434 // rkprintf("[Kernel] ** Code at %012lx is trying to access the SysBase at 4UL.\n", regs.return_rip);
436 if ( (ip
[0] & 0xfb) == 0x48 &&
438 (ip
[2] & 0xc7) == 0x04 &&
442 int reg
= ((ip
[2] >> 3) & 0x07) | ((ip
[0] & 0x04) << 1);
458 // case 4: /* Cannot put SysBase into rSP register */
459 // regs.return_rsp = SysBase;
496 regs
.return_rip
+= 8;
500 else if ( (ip
[0] & 0xfb) == 0x48 &&
502 (ip
[2] & 0xc7) == 0x05
505 int reg
= ((ip
[2] >> 3) & 0x07) | ((ip
[0] & 0x04) << 1);
521 // case 4: /* Cannot put SysBase into rSP register */
522 // regs.return_rsp = SysBase;
559 regs
.return_rip
+= 7;
567 rkprintf("IRQ %02x:", regs
.irq_number
);
568 rkprintf("[Kernel] PAGE FAULT EXCEPTION! %016p\n",ptr
);
572 rkprintf("[Kernel] %s %p '%s'\n",
573 t
->tc_Node
.ln_Type
== NT_TASK
?"task":"process", t
, t
->tc_Node
.ln_Name
);
576 rkprintf("[Kernel] stack=%04x:%012x rflags=%016x ip=%04x:%012x err=%08x\n",
577 regs
.return_ss
, regs
.return_rsp
, regs
.return_rflags
,
578 regs
.return_cs
, regs
.return_rip
, regs
.error_code
);
580 rkprintf("[Kernel] rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n", regs
.rax
, regs
.rbx
, regs
.rcx
, regs
.rdx
);
581 rkprintf("[Kernel] rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n", regs
.rsi
, regs
.rdi
, regs
.rbp
, regs
.return_rsp
);
582 rkprintf("[Kernel] r08=%016lx r09=%016lx r10=%016lx r11=%016lx\n", regs
.r8
, regs
.r9
, regs
.r10
, regs
.r11
);
583 rkprintf("[Kernel] r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n", regs
.r12
, regs
.r13
, regs
.r14
, regs
.r15
);
584 rkprintf("[Kernel] *rsp=%016lx\n", *(uint64_t *)regs
.return_rsp
);
586 rkprintf("[Kernel] Insn: ");
587 for (i
= 0; i
< 16; i
++)
588 rkprintf("%02x ", ip
[i
]);
593 else if (regs
.irq_number
== 0x80) /* Syscall? */
602 core_Dispatch(®s
);
610 if (regs
.ds
!= KERNEL_DS
)
611 core_Schedule(®s
);
618 if (KernelBase
->kb_Intr
[regs
.irq_number
].lh_Type
== KBL_APIC
)
619 core_APIC_AckIntr(regs
.irq_number
);
621 if (KernelBase
->kb_Intr
[regs
.irq_number
].lh_Type
== KBL_XTPIC
)
622 core_XTPIC_AckIntr(regs
.irq_number
);
625 if (!IsListEmpty(&KernelBase
->kb_Intr
[regs
.irq_number
]))
627 struct IntrNode
*in
, *in2
;
629 ForeachNodeSafe(&KernelBase
->kb_Intr
[regs
.irq_number
], in
, in2
)
632 in
->in_Handler(in
->in_HandlerData
, in
->in_HandlerData2
);
635 if (KernelBase
->kb_Intr
[regs
.irq_number
].lh_Type
== KBL_XTPIC
)
636 core_XTPIC_EnableIRQ(regs
.irq_number
);
640 while (die
) asm volatile ("hlt");
644 ".globl core_DefaultIRETQ\n\t"
645 ".type core_DefaultIRETQ,@function\n"
646 "core_DefaultIRETQ: iretq");