d4ffdd78ac408ebdecf0e90246de75a950d3d8be
[akaros.git] / kern / arch / x86 / trapentry32.S
1 /* See COPYRIGHT for copyright information.
2  * The two TRAP* macros (minus the .data parts) are from the JOS project.
3  * Everything else:
4  * Copyright (c) 2009 The Regents of the University of California
5  * Barret Rhoden <brho@cs.berkeley.edu>
6  * See LICENSE for details.
7  */
8 #include <arch/mmu.h>
9 #include <arch/trap.h>
10 #include <ros/memlayout.h>
11
12 ###################################################################
13 # exceptions/interrupts
14 ###################################################################
15
16 /* The TRAPHANDLER macro defines a globally-visible function for handling
17  * a trap.  It pushes a trap number onto the stack, then jumps to _alltraps.
18  * It also builds this traps portion of the trap_tbl.
19  * Use TRAPHANDLER for traps where the CPU automatically pushes an error code.
20  */
21 #define TRAPHANDLER(name, num)                                                                  \
22         .text;                                                                                                          \
23         .globl name;            /* define global symbol for 'name' */   \
24         .type name, @function;  /* symbol type is function */           \
25         .align 2;               /* align function definition */                         \
26         name:                   /* function starts here */                                      \
27         pushl $(num);                                                                                           \
28         jmp _alltraps;                                                                                          \
29         .data;                                                                                                          \
30         .long name;                                                                                                     \
31         .long num
32
33 /* Use TRAPHANDLER_NOEC for traps where the CPU doesn't push an error code.
34  * It pushes a 0 in place of the error code, so the trap frame has the same
35  * format in either case.
36  */
37 #define TRAPHANDLER_NOEC(name, num)             \
38         .text;                                                          \
39         .globl name;                                            \
40         .type name, @function;                          \
41         .align 2;                                                       \
42         name:                                                           \
43         pushl $0;                                                       \
44         pushl $(num);                                           \
45         jmp _alltraps;                                          \
46         .data;                                                          \
47         .long name;                                                     \
48         .long num
49
50 /* Same as NOEC, but for IRQs instead.  num is the ISR number it is mapped to */
51 #define IRQ_HANDLER(name, num)                  \
52         .text;                                                          \
53         .globl name;                                            \
54         .type name, @function;                          \
55         .align 2;                                                       \
56         name:                                                           \
57         pushl $0;                                                       \
58         pushl $(num);                                           \
59         jmp _allirqs;                                           \
60         .data;                                                          \
61         .long name;                                                     \
62         .long num
63
64 /* Only used in the kernel during SMP boot.  Send a LAPIC_EOI and iret. */
65 #define POKE_HANDLER(name, num)                 \
66         .text;                                                          \
67         .globl name;                                            \
68         .type name, @function;                          \
69         .align 2;                                                       \
70         name:;                                                          \
71         movl $0, (LAPIC_BASE + 0x0b0);      \
72         iret;                                                           \
73         .data;                                                          \
74         .long name;                                                     \
75         .long num
76
77 /* Same as above, but takes a specific function to jump to.  See comments
78  * below from _allirqs for details.
79  */
80 #define IRQ_HANDLER_SPEC(name, num, func)                                      \
81         .text;                                                                                                 \
82         .globl name;                                                                                   \
83         .type name, @function;                                                                 \
84         .align 2;                                                                                              \
85         name:                                                                                                  \
86         pushl $0;                                                                  \
87         pushl $(num);                                                              \
88         cld;                                                                       \
89         pushl %ds;                                                                 \
90         pushl %es;                                                                 \
91         pushl %fs;                                                                 \
92         pushl %gs;                                                                 \
93         pushal;                                                                    \
94         movw $0, %ax;                                                              \
95         movw %ax, %gs;                                                             \
96         movw %ax, %fs;                                                             \
97         movw $GD_KD, %ax;                                                          \
98         movw %ax, %ds;                                                             \
99         movw %ax, %es;                                                             \
100         pushl %esp;                                                                \
101         movl $0, %ebp;                                                             \
102         call (func);                                                               \
103         popl %esp;                                                                 \
104         popal;                                                                     \
105         popl %gs;                                                                  \
106         popl %fs;                                                                  \
107         popl %es;                                                                  \
108         popl %ds;                                                                  \
109         addl $0x8, %esp;                                                           \
110         iret;                                                                      \
111         .data;                                                                     \
112         .long name;                                                                \
113         .long num
114
115 .data
116 .globl trap_tbl
117 trap_tbl:
118
119 /*
120  * Generate entry points for the different traps.
121  */
122 TRAPHANDLER_NOEC(ISR_divide_error, T_DIVIDE)
123 TRAPHANDLER_NOEC(ISR_debug_exceptions, T_DEBUG)
124 TRAPHANDLER_NOEC(ISR_NMI, T_NMI)
125 TRAPHANDLER_NOEC(ISR_breakpoint, T_BRKPT)
126 TRAPHANDLER_NOEC(ISR_overflow, T_OFLOW)
127 TRAPHANDLER_NOEC(ISR_bounds_check, T_BOUND)
128 TRAPHANDLER_NOEC(ISR_invalid_opcode, T_ILLOP)
129 TRAPHANDLER_NOEC(ISR_device_not_available, T_DEVICE)
130 /* supposedly, DF generates an error code, but the one time we've had a DF so
131  * far, it didn't.  eventually, this should probably be handled with a task gate
132  * it might have pushed a 0, but just the rest of the stack was corrupt
133  */
134 TRAPHANDLER_NOEC(ISR_double_fault, T_DBLFLT)
135 /* 9 reserved */
136 TRAPHANDLER(ISR_invalid_TSS, T_TSS)
137 TRAPHANDLER(ISR_segment_not_present, T_SEGNP)
138 TRAPHANDLER(ISR_stack_exception, T_STACK)
139 TRAPHANDLER(ISR_general_protection_fault, T_GPFLT)
140 TRAPHANDLER(ISR_page_fault, T_PGFLT)
141 /* 15 reserved */
142 TRAPHANDLER_NOEC(ISR_floating_point_error, T_FPERR)
143 TRAPHANDLER(ISR_alignment_check, T_ALIGN)
144 TRAPHANDLER_NOEC(ISR_machine_check, T_MCHK)
145 TRAPHANDLER_NOEC(ISR_simd_error, T_SIMDERR)
146 /* 20 - 31 reserved */
147 IRQ_HANDLER(IRQ0, 32)
148 IRQ_HANDLER(IRQ1, 33)
149 IRQ_HANDLER(IRQ2, 34)
150 IRQ_HANDLER(IRQ3, 35)
151 IRQ_HANDLER(IRQ4, 36)
152 IRQ_HANDLER(IRQ5, 37)
153 IRQ_HANDLER(IRQ6, 38)
154 IRQ_HANDLER(IRQ7, 39)
155 IRQ_HANDLER(IRQ8, 40)
156 IRQ_HANDLER(IRQ9, 41)
157 IRQ_HANDLER(IRQ10, 42)
158 IRQ_HANDLER(IRQ11, 43)
159 IRQ_HANDLER(IRQ12, 44)
160 IRQ_HANDLER(IRQ13, 45)
161 IRQ_HANDLER(IRQ14, 46)
162 IRQ_HANDLER(IRQ15, 47)
163 /* 25 general purpose vectors, for use by the LAPIC.  Can expand later. */
164 IRQ_HANDLER(IRQ198, I_TESTING) # used in testing.c
165 IRQ_HANDLER(IRQ199, 231)
166 IRQ_HANDLER(IRQ200, 232)
167 IRQ_HANDLER(IRQ201, 233)
168 IRQ_HANDLER(IRQ202, 234)
169 IRQ_HANDLER(IRQ203, 235)
170 IRQ_HANDLER(IRQ204, 236)
171 IRQ_HANDLER(IRQ205, 237)
172 IRQ_HANDLER(IRQ206, 238)
173 IRQ_HANDLER(IRQ207, 239)
174 /* 0xf0 - start of the SMP_CALL IPIS */
175 IRQ_HANDLER(IRQ208, I_SMP_CALL0)
176 IRQ_HANDLER(IRQ209, I_SMP_CALL1)
177 IRQ_HANDLER(IRQ210, I_SMP_CALL2)
178 IRQ_HANDLER(IRQ211, I_SMP_CALL3)
179 IRQ_HANDLER(IRQ212, I_SMP_CALL4)
180 IRQ_HANDLER(IRQ213, 245)
181 IRQ_HANDLER(IRQ214, 246)
182 IRQ_HANDLER(IRQ215, 247)
183 IRQ_HANDLER(IRQ216, 248)
184 IRQ_HANDLER(IRQ217, 249)
185 IRQ_HANDLER(IRQ218, 250)
186 IRQ_HANDLER(IRQ219, 251)
187 IRQ_HANDLER(IRQ220, 252)
188 IRQ_HANDLER(IRQ221, 253)
189 POKE_HANDLER(IRQ222, 254)
190 IRQ_HANDLER(IRQ223, I_KERNEL_MSG)
191
192 /* Technically, these HANDLER entries do not need to be in numeric order */
193 TRAPHANDLER_NOEC(ISR_syscall, T_SYSCALL)
194 /* But make sure default is last!! */
195 TRAPHANDLER_NOEC(ISR_default, T_DEFAULT)
196
197 .data
198 .globl trap_tbl_end
199 trap_tbl_end:
200
201 /* Keep the exit paths of _alltraps, _allirqs, and sysenter_handler in sync
202  * with the corresponding pop_tf's.
203  */
204 .text
205 _alltraps:
206         cld
207         pushl %ds
208         pushl %es
209         pushl %fs
210         pushl %gs
211         pushal
212         movw $0, %ax;
213         movw %ax, %gs;
214         movw %ax, %fs;
215         movw $GD_KD, %ax                # data segments aren't accessible by default
216         movw %ax, %ds
217         movw %ax, %es
218         pushl %esp
219         movl $0, %ebp                   # so we can backtrace to this point
220         call trap
221         popl %esp
222         popal
223         popl %gs
224         popl %fs
225         popl %es
226         popl %ds
227         addl $0x8, %esp                 # skip trapno and err
228         iret
229
230 /* will need to think about when we reenable interrupts.  right now, iret does it,
231  * if the previous EFLAGS had interrupts enabled
232  */
233 _allirqs:
234         cld
235         pushl %ds
236         pushl %es
237         pushl %fs
238         pushl %gs
239         pushal
240         movw $0, %ax;
241         movw %ax, %gs;
242         movw %ax, %fs;
243         movw $GD_KD, %ax                # data segments aren't accessible by default
244         movw %ax, %ds
245         movw %ax, %es
246         pushl %esp
247         movl $0, %ebp                   # so we can backtrace to this point
248         call irq_handler
249         popl %esp
250         popal
251         popl %gs
252         popl %fs
253         popl %es
254         popl %ds
255         addl $0x8, %esp                 # skip IRQ number and err (which is 0)
256         iret
257
258 .globl sysenter_handler;
259 .type sysenter_handler, @function;
260 # All of the pushl zeros are to keep the trap frame looking the same as when we
261 # receive a trap or an interrupt
262 sysenter_handler:
263         cld
264         pushl $0                                # ss
265         pushl $0                                # esp
266         pushfl                                  # eflags
267         pushl $0                                # CS == 0 lets the kernel know it was a sysenter        
268         pushl $0                                # eip
269         pushl $0                                # err 
270         pushl $T_SYSCALL                # helps with print_trapframe
271         pushl %ds
272         pushl %es
273         pushl %fs
274         pushl %gs
275         pushal
276         movw $0, %ax;
277         movw %ax, %gs;
278         movw %ax, %fs;
279         movw $GD_KD, %ax
280         movw %ax, %ds
281         movw %ax, %es
282         pushl %esp
283         movl $0, %ebp                   # so we can backtrace to this point
284         call sysenter_callwrapper
285         popl %esp
286         popal
287         popl %gs
288         popl %fs
289         popl %es
290         popl %ds
291         addl $0x10, %esp                # pop T_SYSCALL and the three zeros
292         popfl                                   # restore EFLAGS (and usually enables interrupts!)
293         movl %ebp, %ecx
294         sti                                             # interrupts are turned off when starting a core
295         sysexit