2 Copyright © 1995-2016, The AROS Development Team. All rights reserved.
7 #include <proto/exec.h>
10 #include "kernel_base.h"
11 #include "kernel_debug.h"
12 #include "kernel_globals.h"
13 #include "kernel_intern.h"
14 #include "kernel_interrupts.h"
15 #include "kernel_intr.h"
16 #include "kernel_syscall.h"
25 return address of these exceptions is the address of faulting instr
27 return address is address of instruction followed by trapping instr
28 (1 can be FAULT and TRAP)
30 ABORT = ??? (no information = no return address)
85 typedef void (*trap_type
)(void);
87 const trap_type traps
[48] =
139 #define _set_gate(gate_addr,type,dpl,addr) \
142 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
144 "movl %%eax,%0\n\t" \
146 :"=m" (*((long *) (gate_addr))), \
147 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
148 :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
149 "3" ((char *) (addr)),"2" (KERNEL_CS << 16)); \
152 void set_intr_gate(unsigned int n
, void *addr
)
154 struct PlatformData
*data
= KernelBase
->kb_PlatformData
;
156 _set_gate(&data
->idt
[n
], 14, 0, addr
);
159 void set_system_gate(unsigned int n
, void *addr
)
161 struct PlatformData
*data
= KernelBase
->kb_PlatformData
;
163 _set_gate(&data
->idt
[n
], 14, 3, addr
);
166 void handleException(struct ExceptionContext
*regs
, unsigned long error_code
, unsigned long irq_number
)
168 struct KernelBase
*KernelBase
= getKernelBase();
170 if (irq_number
< 0x20)
172 /* These are CPU traps */
173 cpu_Trap(regs
, error_code
, irq_number
);
175 else if ((irq_number
>= 0x20) && (irq_number
< 0x30)) /* XT-PIC IRQ */
177 /* From CPU's point of view, IRQs are exceptions starting from 0x20. */
180 if (irq_number
== 13)
188 XTPIC_AckIntr(irq_number
, &KernelBase
->kb_PlatformData
->xtpic_mask
);
189 krnRunIRQHandlers(KernelBase
, irq_number
);
192 * Interrupt acknowledge on XT-PIC also disables this interrupt.
193 * If we still need it, we need to re-enable it.
195 if (!IsListEmpty(&KernelBase
->kb_Interrupts
[irq_number
]))
197 XTPIC_EnableIRQ(irq_number
, &KernelBase
->kb_PlatformData
->xtpic_mask
);
201 /* Upon exit from the lowest-level hardware IRQ we run the task scheduler */
202 if (SysBase
&& (regs
->ds
!= KERNEL_DS
))
204 /* Disable interrupts for a while */
205 __asm__
__volatile__("cli; cld;");
207 core_ExitInterrupt(regs
);
210 else if (irq_number
== 0x80) /* Syscall? */
212 /* Syscall number is actually ULONG (we use only eax) */
213 ULONG sc
= regs
->eax
;
215 DSYSCALL(bug("[Kernel] Syscall %u\n", sc
));
217 /* The following syscalls can be run in both supervisor and user mode */
221 D(bug("[Kernel] Warm restart\n"));
225 /* This doesn't return */
226 core_Supervisor(regs
);
230 * Scheduler can be called only from within user mode.
231 * Every task has ss register initialized to a valid segment descriptor.\
232 * The descriptor itself isn't used by x86; however when a privilege
233 * level switch occurs upon an interrupt, ss is reset to zero. Old ss value
234 * is always pushed to stack as part of interrupt context.
235 * We rely on this in order to determine which CPL we are returning to.
237 if (regs
->ds
!= KERNEL_DS
)
239 DSYSCALL(bug("[Kernel] User-mode syscall\n"));
241 /* Disable interrupts for a while */
242 __asm__
__volatile__("cli; cld;");
244 core_SysCall(sc
, regs
);
247 DSYSCALL(bug("[Kernel] Returning from syscall...\n"));
249 else if (irq_number
== 0xFE)
251 /* APIC error vector */
254 /* Return from this routine is equal to core_LeaveInterrupt(regs) */
257 void Init_Traps(struct PlatformData
*data
)
261 for (i
= 0; i
< 0x30; i
++)
263 _set_gate(&data
->idt
[i
], 14, 0, traps
[i
]);
265 /* Set all unused vectors to dummy interrupt */
266 for (i
= 0x30; i
< 256; i
++)
268 _set_gate(&data
->idt
[i
], 14, 0, core_Unused_Int
);
271 /* Create user interrupt used to enter supervisor mode */
272 _set_gate(&data
->idt
[0x80], 14, 3, TRAP0x80_trap
);
273 /* Create APIC error vector */
274 _set_gate(&data
->idt
[0xFE], 14, 0, TRAP0xFE_trap
);