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