39b45f47a651b4c05e2b0155f28dff1056751830
[akaros.git] / kern / arch / x86 / trapentry64.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         pushq $(num);                                                                                           \
28         jmp _alltraps;                                                                                          \
29         .data;                                                                                                          \
30         .quad 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         pushq $0;                                                       \
44         pushq $(num);                                           \
45         jmp _alltraps;                                          \
46         .data;                                                          \
47         .quad 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         pushq $0;                                                       \
58         pushq $(num);                                           \
59         jmp _allirqs;                                           \
60         .data;                                                          \
61         .quad 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         pushq $0;                                                                  \
74         pushq $(num);                                                              \
75         cld;                                                                       \
76         pushq %ds;                                                                 \
77         pushq %es;                                                                 \
78         pushq %fs;                                                                 \
79         pushq %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         pushq %rsp;                                                                \
88         movq $0, %rbp;                                                             \
89         call (func);                                                               \
90         popq %rsp;                                                                 \
91         # popal;                                                                   \
92         popq %gs;                                                                  \
93         popq %fs;                                                                  \
94         popq %es;                                                                  \
95         popq %ds;                                                                  \
96         addl $0x8, %rsp;                                                           \
97         iret;                                                                      \
98         .data;                                                                     \
99         .quad 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(IRQ223, I_KERNEL_MSG)
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 corrrsponding pop_tf's.
190  */
191 .text
192 _alltraps:
193         cld
194         # pushq %ds
195         # pushq %es
196         pushq %fs
197         pushq %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         pushq %rsp
204         movq $0, %rbp                   # so we can backtrace to this point
205         call trap
206         popq %rsp
207         # popal
208         popq %gs
209         popq %fs
210         # popq %es
211         # popq %ds
212         addq $0x8, %rsp                 # skip trapno and err
213         iret
214
215 /* will need to think about when we reenable interrupts.  right now, iret does it,
216  * if the previous EFLAGS had interrupts enabled
217  */
218 _allirqs:
219         cld
220         # pushq %ds
221         # pushq %es
222         pushq %fs
223         pushq %gs
224         # pushal
225         movw $0, %ax;
226         movw %ax, %gs;
227         movw %ax, %fs;
228         movw $GD_KD, %ax                # data segments aren't accessible by default
229         movw %ax, %ds
230         movw %ax, %es
231         pushq %rsp
232         movq $0, %rbp                   # so we can backtrace to this point
233         call irq_handler
234         popq %rsp
235         # popal
236         popq %gs
237         popq %fs
238         # popq %es
239         # popq %ds
240         addq $0x8, %rsp                 # skip IRQ number and err (which is 0)
241         iret
242
243 .globl sysenter_handler;
244 .type sysenter_handler, @function;
245 # All of the pushq zeros are to keep the trap frame looking the same as when we
246 # receive a trap or an interrupt
247 sysenter_handler:
248         cld
249         pushq $0                                # ss
250         pushq $0                                # rsp
251         pushfq                                  # eflags
252         pushq $0                                # CS == 0 lets the kernel know it was a sysenter        
253         pushq $0                                # eip
254         pushq $0                                # err 
255         pushq $T_SYSCALL                # helps with print_trapframe
256         # pushq %ds
257         # pushq %es
258         pushq %fs
259         pushq %gs
260         # pushal
261         movw $0, %ax;
262         movw %ax, %gs;
263         movw %ax, %fs;
264         movw $GD_KD, %ax
265         movw %ax, %ds
266         movw %ax, %es
267         pushq %rsp
268         movq $0, %rbp                   # so we can backtrace to this point
269         call sysenter_callwrapper
270         popq %rsp
271         # popal
272         popq %gs
273         popq %fs
274         # popq %es
275         # popq %ds
276         addq $0x10, %rsp                # pop T_SYSCALL and the three zeros
277         popfq                                   # restore EFLAGS (and usually enables interrupts!)
278         movq %rbp, %rcx
279         sti                                             # interrupts are turned off when starting a core
280         sysexit