Fixes trapframes on x86
[akaros.git] / kern / arch / i386 / trapentry.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 /* Same as above, but takes a specific function to jump to.  See comments
65  * below from _allirqs for details.
66  */
67 #define IRQ_HANDLER_SPEC(name, num, func)                                      \
68         .text;                                                                                                 \
69         .globl name;                                                                                   \
70         .type name, @function;                                                                 \
71         .align 2;                                                                                              \
72         name:                                                                                                  \
73         pushl $0;                                                                  \
74         pushl $(num);                                                              \
75         cld;                                                                       \
76         pushl %ds;                                                                 \
77         pushl %es;                                                                 \
78         pushl %fs;                                                                 \
79         pushl %gs;                                                                 \
80         pushal;                                                                    \
81         movw $GD_KD, %ax;                                                          \
82         movw %ax, %ds;                                                             \
83         movw %ax, %es;                                                             \
84         pushl %esp;                                                                \
85         movl $0, %ebp;                                                             \
86         call (func);                                                               \
87         popl %esp;                                                                 \
88         popal;                                                                     \
89         popl %gs;                                                                  \
90         popl %fs;                                                                  \
91         popl %es;                                                                  \
92         popl %ds;                                                                  \
93         addl $0x8, %esp;                                                           \
94         iret;                                                                      \
95         .data;                                                                     \
96         .long name;                                                                \
97         .long num
98
99 .data
100 .globl trap_tbl
101 trap_tbl:
102
103 /*
104  * Generate entry points for the different traps.
105  */
106 TRAPHANDLER_NOEC(ISR_divide_error, T_DIVIDE)
107 TRAPHANDLER_NOEC(ISR_debug_exceptions, T_DEBUG)
108 TRAPHANDLER_NOEC(ISR_NMI, T_NMI)
109 TRAPHANDLER_NOEC(ISR_breakpoint, T_BRKPT)
110 TRAPHANDLER_NOEC(ISR_overflow, T_OFLOW)
111 TRAPHANDLER_NOEC(ISR_bounds_check, T_BOUND)
112 TRAPHANDLER_NOEC(ISR_invalid_opcode, T_ILLOP)
113 TRAPHANDLER_NOEC(ISR_device_not_available, T_DEVICE)
114 /* supposedly, DF generates an error code, but the one time we've had a DF so
115  * far, it didn't.  eventually, this should probably be handled with a task gate
116  * it might have pushed a 0, but just the rest of the stack was corrupt
117  */
118 TRAPHANDLER_NOEC(ISR_double_fault, T_DBLFLT)
119 /* 9 reserved */
120 TRAPHANDLER(ISR_invalid_TSS, T_TSS)
121 TRAPHANDLER(ISR_segment_not_present, T_SEGNP)
122 TRAPHANDLER(ISR_stack_exception, T_STACK)
123 TRAPHANDLER(ISR_general_protection_fault, T_GPFLT)
124 TRAPHANDLER(ISR_page_fault, T_PGFLT)
125 /* 15 reserved */
126 TRAPHANDLER_NOEC(ISR_floating_point_error, T_FPERR)
127 TRAPHANDLER(ISR_alignment_check, T_ALIGN)
128 TRAPHANDLER_NOEC(ISR_machine_check, T_MCHK)
129 TRAPHANDLER_NOEC(ISR_simd_error, T_SIMDERR)
130 /* 20 - 31 reserved */
131 IRQ_HANDLER(IRQ0, 32)
132 IRQ_HANDLER(IRQ1, 33)
133 IRQ_HANDLER(IRQ2, 34)
134 IRQ_HANDLER(IRQ3, 35)
135 IRQ_HANDLER(IRQ4, 36)
136 IRQ_HANDLER(IRQ5, 37)
137 IRQ_HANDLER(IRQ6, 38)
138 IRQ_HANDLER(IRQ7, 39)
139 IRQ_HANDLER(IRQ8, 40)
140 IRQ_HANDLER(IRQ9, 41)
141 IRQ_HANDLER(IRQ10, 42)
142 IRQ_HANDLER(IRQ11, 43)
143 IRQ_HANDLER(IRQ12, 44)
144 IRQ_HANDLER(IRQ13, 45)
145 IRQ_HANDLER(IRQ14, 46)
146 IRQ_HANDLER(IRQ15, 47)
147 /* 25 general purpose vectors, for use by the LAPIC.  Can expand later. */
148 IRQ_HANDLER(IRQ198, I_TESTING) # used in testing.c
149 IRQ_HANDLER(IRQ199, 231)
150 IRQ_HANDLER(IRQ200, 232)
151 IRQ_HANDLER(IRQ201, 233)
152 IRQ_HANDLER(IRQ202, 234)
153 IRQ_HANDLER(IRQ203, 235)
154 IRQ_HANDLER(IRQ204, 236)
155 IRQ_HANDLER(IRQ205, 237)
156 IRQ_HANDLER(IRQ206, 238)
157 IRQ_HANDLER(IRQ207, 239)
158 /* 0xf0 - start of the SMP_CALL IPIS */
159 IRQ_HANDLER(IRQ208, I_SMP_CALL0)
160 IRQ_HANDLER(IRQ209, I_SMP_CALL1)
161 IRQ_HANDLER(IRQ210, I_SMP_CALL2)
162 IRQ_HANDLER(IRQ211, I_SMP_CALL3)
163 IRQ_HANDLER(IRQ212, I_SMP_CALL4)
164 IRQ_HANDLER(IRQ213, 245)
165 IRQ_HANDLER(IRQ214, 246)
166 IRQ_HANDLER(IRQ215, 247)
167 IRQ_HANDLER(IRQ216, 248)
168 IRQ_HANDLER(IRQ217, 249)
169 IRQ_HANDLER(IRQ218, 250)
170 IRQ_HANDLER(IRQ219, 251)
171 IRQ_HANDLER(IRQ220, 252)
172 IRQ_HANDLER(IRQ221, 253)
173 IRQ_HANDLER(IRQ222, 254)
174 IRQ_HANDLER_SPEC(IRQ223, I_ACTIVE_MSG, __active_message)
175
176 /* Technically, these HANDLER entries do not need to be in numeric order */
177 TRAPHANDLER_NOEC(ISR_syscall, T_SYSCALL)
178 /* But make sure default is last!! */
179 TRAPHANDLER_NOEC(ISR_default, T_DEFAULT)
180
181 .data
182 .globl trap_tbl_end
183 trap_tbl_end:
184
185 /* Keep the exit paths of _alltraps, _allirqs, and sysenter_handler in sync
186  * with the corresponding pop_tf's.
187  */
188 .text
189 _alltraps:
190         cld
191         pushl %ds
192         pushl %es
193         pushl %fs
194         pushl %gs
195         pushal
196         movw $GD_KD, %ax                # data segments aren't accessible by default
197         movw %ax, %ds
198         movw %ax, %es
199         pushl %esp
200         movl $0, %ebp                   # so we can backtrace to this point
201         call trap
202         popl %esp
203         popal
204         popl %gs
205         popl %fs
206         popl %es
207         popl %ds
208         addl $0x8, %esp                 # skip trapno and err
209         iret
210
211 /* will need to think about when we reenable interrupts.  right now, iret does it,
212  * if the previous EFLAGS had interrupts enabled
213  */
214 _allirqs:
215         cld
216         pushl %ds
217         pushl %es
218         pushl %fs
219         pushl %gs
220         pushal
221         movw $GD_KD, %ax                # data segments aren't accessible by default
222         movw %ax, %ds
223         movw %ax, %es
224         pushl %esp
225         movl $0, %ebp                   # so we can backtrace to this point
226         call irq_handler
227         popl %esp
228         popal
229         popl %gs
230         popl %fs
231         popl %es
232         popl %ds
233         addl $0x8, %esp                 # skip IRQ number and err (which is 0)
234         iret
235
236 .globl sysenter_handler;
237 .type sysenter_handler, @function;
238 sysenter_handler:
239         sti                                             # enable interrupts (things are sane here)
240         cld
241         pushfl                                  # save the eflags
242         pushl $0                                # these zeros keep the trapframe looking the same
243         pushl $0                                # as when we receive a trap or interrupt
244         pushl $0                                # and CS == 0 lets the kernel know it was a sysenter
245         pushl $T_SYSCALL                # helps with print_trapframe
246         pushl %ds
247         pushl %es
248         pushl %fs
249         pushl %gs
250         pushal
251         movw $GD_KD, %ax
252         movw %ax, %ds
253         movw %ax, %es
254         pushl %esp
255         movl $0, %ebp                   # so we can backtrace to this point
256         call sysenter_callwrapper
257         popl %esp
258         popal
259         popl %gs
260         popl %fs
261         popl %es
262         popl %ds
263         addl $0x10, %esp                # pop T_SYSCALL and the three zeros
264         popfl                                   # restore EFLAGS (and usually enables interrupts!)
265         movl %ebp, %ecx
266         movl %esi, %edx
267         sti                                             # interrupts are turned off when starting a core
268         sysexit