tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / arch / i386-pc / kernel / traps.c
blob33180b32d130e8c0e8f4cc2c5a6c0bb85e46f460
1 /*
2 Copyright © 1995-2016, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <asm/io.h>
7 #include <proto/exec.h>
9 #include "cpu_traps.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"
17 #include "apic.h"
18 #include "traps.h"
19 #include "xtpic.h"
21 #define D(x)
22 #define DSYSCALL(x)
24 /* 0,1,5-7,9-17,19:
25 return address of these exceptions is the address of faulting instr
26 1,3,4:
27 return address is address of instruction followed by trapping instr
28 (1 can be FAULT and TRAP)
29 others:
30 ABORT = ??? (no information = no return address)
33 BUILD_TRAP(0x00)
34 BUILD_TRAP(0x01)
35 BUILD_TRAP(0x02)
36 BUILD_TRAP(0x03)
37 BUILD_TRAP(0x04)
38 BUILD_TRAP(0x05)
39 BUILD_TRAP(0x06)
40 BUILD_TRAP(0x07)
41 BUILD_TRAP(0x08)
42 BUILD_TRAP(0x09)
43 BUILD_TRAP(0x0a)
44 BUILD_TRAP(0x0b)
45 BUILD_TRAP(0x0c)
46 BUILD_TRAP(0x0d)
47 BUILD_TRAP(0x0e)
48 BUILD_TRAP(0x0f)
49 BUILD_TRAP(0x10)
50 BUILD_TRAP(0x11)
51 BUILD_TRAP(0x12)
52 BUILD_TRAP(0x13)
53 BUILD_TRAP(0x14)
54 BUILD_TRAP(0x15)
55 BUILD_TRAP(0x16)
56 BUILD_TRAP(0x17)
57 BUILD_TRAP(0x18)
58 BUILD_TRAP(0x19)
59 BUILD_TRAP(0x1a)
60 BUILD_TRAP(0x1b)
61 BUILD_TRAP(0x1c)
62 BUILD_TRAP(0x1d)
63 BUILD_TRAP(0x1e)
64 BUILD_TRAP(0x1f)
65 BUILD_TRAP(0x20)
66 BUILD_TRAP(0x21)
67 BUILD_TRAP(0x22)
68 BUILD_TRAP(0x23)
69 BUILD_TRAP(0x24)
70 BUILD_TRAP(0x25)
71 BUILD_TRAP(0x26)
72 BUILD_TRAP(0x27)
73 BUILD_TRAP(0x28)
74 BUILD_TRAP(0x29)
75 BUILD_TRAP(0x2a)
76 BUILD_TRAP(0x2b)
77 BUILD_TRAP(0x2c)
78 BUILD_TRAP(0x2d)
79 BUILD_TRAP(0x2e)
80 BUILD_TRAP(0x2f)
82 BUILD_TRAP(0x80)
83 BUILD_TRAP(0xFE)
85 typedef void (*trap_type)(void);
87 const trap_type traps[48] =
89 TRAP0x00_trap,
90 TRAP0x01_trap,
91 TRAP0x02_trap,
92 TRAP0x03_trap,
93 TRAP0x04_trap,
94 TRAP0x05_trap,
95 TRAP0x06_trap,
96 TRAP0x07_trap,
97 TRAP0x08_trap,
98 TRAP0x09_trap,
99 TRAP0x0a_trap,
100 TRAP0x0b_trap,
101 TRAP0x0c_trap,
102 TRAP0x0d_trap,
103 TRAP0x0e_trap,
104 TRAP0x0f_trap,
105 TRAP0x10_trap,
106 TRAP0x11_trap,
107 TRAP0x12_trap,
108 TRAP0x13_trap,
109 TRAP0x14_trap,
110 TRAP0x15_trap,
111 TRAP0x16_trap,
112 TRAP0x17_trap,
113 TRAP0x18_trap,
114 TRAP0x19_trap,
115 TRAP0x1a_trap,
116 TRAP0x1b_trap,
117 TRAP0x1c_trap,
118 TRAP0x1d_trap,
119 TRAP0x1e_trap,
120 TRAP0x1f_trap,
121 TRAP0x20_trap,
122 TRAP0x21_trap,
123 TRAP0x22_trap,
124 TRAP0x23_trap,
125 TRAP0x24_trap,
126 TRAP0x25_trap,
127 TRAP0x26_trap,
128 TRAP0x27_trap,
129 TRAP0x28_trap,
130 TRAP0x29_trap,
131 TRAP0x2a_trap,
132 TRAP0x2b_trap,
133 TRAP0x2c_trap,
134 TRAP0x2d_trap,
135 TRAP0x2e_trap,
136 TRAP0x2f_trap
139 #define _set_gate(gate_addr,type,dpl,addr) \
140 do { \
141 int __d0, __d1; \
142 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
143 "movw %4,%%dx\n\t" \
144 "movl %%eax,%0\n\t" \
145 "movl %%edx,%1" \
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)); \
150 } while (0)
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. */
178 irq_number -= 0x20;
180 if (irq_number == 13)
182 /* FPU error IRQ */
183 outb(0, 0xF0);
186 if (KernelBase)
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 */
218 switch (sc)
220 case SC_REBOOT:
221 D(bug("[Kernel] Warm restart\n"));
222 core_Reboot();
224 case SC_SUPERVISOR:
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 */
252 core_APIC_AckIntr();
254 /* Return from this routine is equal to core_LeaveInterrupt(regs) */
257 void Init_Traps(struct PlatformData *data)
259 int i;
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);