8bfc157fc846c900fc64dc4659ad49736e494ba8
[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, 2013 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 #define TRAPHANDLER_NOEC(name, num)             \
37         .text;                                                          \
38         .globl name;                                            \
39         .type name, @function;                          \
40         .align 2;                                                       \
41         name:                                                           \
42         pushq $0;                                                       \
43         pushq $(num);                                           \
44         jmp _alltraps;                                          \
45         .data;                                                          \
46         .quad name;                                                     \
47         .long num
48
49 /* Same as NOEC, but for IRQs instead.  num is the ISR number it is mapped to */
50 #define IRQ_HANDLER(name, num)                  \
51         .text;                                                          \
52         .globl name;                                            \
53         .type name, @function;                          \
54         .align 2;                                                       \
55         name:                                                           \
56         pushq $0;                                                       \
57         pushq $(num);                                           \
58         jmp _allirqs;                                           \
59         .data;                                                          \
60         .quad name;                                                     \
61         .long num
62
63 .data
64 .globl trap_tbl
65 trap_tbl:
66
67 /*
68  * Generate entry points for the different traps.
69  */
70 TRAPHANDLER_NOEC(ISR_divide_error, T_DIVIDE)
71 TRAPHANDLER_NOEC(ISR_debug_exceptions, T_DEBUG)
72 TRAPHANDLER_NOEC(ISR_NMI, T_NMI)
73 TRAPHANDLER_NOEC(ISR_breakpoint, T_BRKPT)
74 TRAPHANDLER_NOEC(ISR_overflow, T_OFLOW)
75 TRAPHANDLER_NOEC(ISR_bounds_check, T_BOUND)
76 TRAPHANDLER_NOEC(ISR_invalid_opcode, T_ILLOP)
77 TRAPHANDLER_NOEC(ISR_device_not_available, T_DEVICE)
78 /* supposedly, DF generates an error code, but the one time we've had a DF so
79  * far, it didn't.  eventually, this should probably be handled with a task gate
80  * it might have pushed a 0, but just the rest of the stack was corrupt
81  */
82 TRAPHANDLER_NOEC(ISR_double_fault, T_DBLFLT)
83 /* 9 reserved */
84 TRAPHANDLER(ISR_invalid_TSS, T_TSS)
85 TRAPHANDLER(ISR_segment_not_present, T_SEGNP)
86 TRAPHANDLER(ISR_stack_exception, T_STACK)
87 TRAPHANDLER(ISR_general_protection_fault, T_GPFLT)
88 TRAPHANDLER(ISR_page_fault, T_PGFLT)
89 /* 15 reserved */
90 TRAPHANDLER_NOEC(ISR_floating_point_error, T_FPERR)
91 TRAPHANDLER(ISR_alignment_check, T_ALIGN)
92 TRAPHANDLER_NOEC(ISR_machine_check, T_MCHK)
93 TRAPHANDLER_NOEC(ISR_simd_error, T_SIMDERR)
94 /* 20 - 31 reserved */
95 IRQ_HANDLER(IRQ0, 32)
96 IRQ_HANDLER(IRQ1, 33)
97 IRQ_HANDLER(IRQ2, 34)
98 IRQ_HANDLER(IRQ3, 35)
99 IRQ_HANDLER(IRQ4, 36)
100 IRQ_HANDLER(IRQ5, 37)
101 IRQ_HANDLER(IRQ6, 38)
102 IRQ_HANDLER(IRQ7, 39)
103 IRQ_HANDLER(IRQ8, 40)
104 IRQ_HANDLER(IRQ9, 41)
105 IRQ_HANDLER(IRQ10, 42)
106 IRQ_HANDLER(IRQ11, 43)
107 IRQ_HANDLER(IRQ12, 44)
108 IRQ_HANDLER(IRQ13, 45)
109 IRQ_HANDLER(IRQ14, 46)
110 IRQ_HANDLER(IRQ15, 47)
111 /* 25 general purpose vectors, for use by the LAPIC.  Can expand later. */
112 IRQ_HANDLER(IRQ198, I_TESTING) # used in testing.c
113 IRQ_HANDLER(IRQ199, 231)
114 IRQ_HANDLER(IRQ200, 232)
115 IRQ_HANDLER(IRQ201, 233)
116 IRQ_HANDLER(IRQ202, 234)
117 IRQ_HANDLER(IRQ203, 235)
118 IRQ_HANDLER(IRQ204, 236)
119 IRQ_HANDLER(IRQ205, 237)
120 IRQ_HANDLER(IRQ206, 238)
121 IRQ_HANDLER(IRQ207, 239)
122 /* 0xf0 - start of the SMP_CALL IPIS */
123 IRQ_HANDLER(IRQ208, I_SMP_CALL0)
124 IRQ_HANDLER(IRQ209, I_SMP_CALL1)
125 IRQ_HANDLER(IRQ210, I_SMP_CALL2)
126 IRQ_HANDLER(IRQ211, I_SMP_CALL3)
127 IRQ_HANDLER(IRQ212, I_SMP_CALL4)
128 IRQ_HANDLER(IRQ213, 245)
129 IRQ_HANDLER(IRQ214, 246)
130 IRQ_HANDLER(IRQ215, 247)
131 IRQ_HANDLER(IRQ216, 248)
132 IRQ_HANDLER(IRQ217, 249)
133 IRQ_HANDLER(IRQ218, 250)
134 IRQ_HANDLER(IRQ219, 251)
135 IRQ_HANDLER(IRQ220, 252)
136 IRQ_HANDLER(IRQ221, 253)
137 IRQ_HANDLER(IRQ222, 254)
138 IRQ_HANDLER(IRQ223, I_KERNEL_MSG)
139
140 /* Technically, these HANDLER entries do not need to be in numeric order */
141 TRAPHANDLER_NOEC(ISR_syscall, T_SYSCALL)
142 /* But make sure default is last!! */
143 TRAPHANDLER_NOEC(ISR_default, T_DEFAULT)
144
145 .data
146 .globl trap_tbl_end
147 trap_tbl_end:
148
149 /* Keep the exit paths of _alltraps, _allirqs, and sysenter_handler in sync
150  * with the corrrsponding pop_tf's.  */
151 .text
152 _alltraps:
153         cld
154         /* trapno was pushed, taking up 64 bits.  we're using the upper 32 bits */
155         movw %gs, 0x4(%rsp)
156         movw %fs, 0x6(%rsp)
157         pushq %r15
158         pushq %r14
159         pushq %r13
160         pushq %r12
161         pushq %r11
162         pushq %r10
163         pushq %r9
164         pushq %r8
165         pushq %rdi
166         pushq %rsi
167         pushq %rbp
168         pushq %rdx
169         pushq %rcx
170         pushq %rbx
171         pushq %rax
172         movq $0, %rbp                   # so we can backtrace to this point
173         movq %rsp, %rdi
174         call trap
175         popq %rax
176         popq %rbx
177         popq %rcx
178         popq %rdx
179         popq %rbp
180         popq %rsi
181         popq %rdi
182         popq %r8
183         popq %r9
184         popq %r10
185         popq %r11
186         popq %r12
187         popq %r13
188         popq %r14
189         popq %r15
190         movw 0x4(%rsp), %gs
191         movw 0x6(%rsp), %fs
192         addq $0x10, %rsp                        # skip gs, fs, trapno, and err
193         iretq
194
195 _allirqs:
196         cld
197         /* trapno was pushed, taking up 64 bits.  we're using the upper 32 bits */
198         movw %gs, 0x4(%rsp)
199         movw %fs, 0x6(%rsp)
200         pushq %r15
201         pushq %r14
202         pushq %r13
203         pushq %r12
204         pushq %r11
205         pushq %r10
206         pushq %r9
207         pushq %r8
208         pushq %rdi
209         pushq %rsi
210         pushq %rbp
211         pushq %rdx
212         pushq %rcx
213         pushq %rbx
214         pushq %rax
215         movq $0, %rbp                   # so we can backtrace to this point
216         movq %rsp, %rdi
217         call irq_handler
218         popq %rax
219         popq %rbx
220         popq %rcx
221         popq %rdx
222         popq %rbp
223         popq %rsi
224         popq %rdi
225         popq %r8
226         popq %r9
227         popq %r10
228         popq %r11
229         popq %r12
230         popq %r13
231         popq %r14
232         popq %r15
233         movw 0x4(%rsp), %gs
234         movw 0x6(%rsp), %fs
235         addq $0x10, %rsp                        # skip gs, fs, trapno, and err (which is 0)
236         iretq
237
238 .globl sysenter_handler;
239 .type sysenter_handler, @function;
240 # All of the pushq zeros are to keep the trap frame looking the same as when we
241 # receive a trap or an interrupt
242 sysenter_handler:
243         cld
244         pushq $0                                # ss
245         pushq $0                                # rsp
246         pushfq                                  # eflags
247         pushq $0                                # CS == 0 lets the kernel know it was a sysenter        
248         pushq $0                                # eip
249         pushq $0                                # err 
250         pushq $T_SYSCALL                # helps with print_trapframe
251         # pushq %ds
252         # pushq %es
253         pushq %fs
254         pushq %gs
255         # pushal
256         movw $0, %ax;
257         movw %ax, %gs;
258         movw %ax, %fs;
259         movw $GD_KD, %ax
260         movw %ax, %ds
261         movw %ax, %es
262         pushq %rsp
263         movq $0, %rbp                   # so we can backtrace to this point
264         call sysenter_callwrapper
265         popq %rsp
266         # popal
267         popq %gs
268         popq %fs
269         # popq %es
270         # popq %ds
271         addq $0x10, %rsp                # pop T_SYSCALL and the three zeros
272         popfq                                   # restore EFLAGS (and usually enables interrupts!)
273         movq %rbp, %rcx
274         sti                                             # interrupts are turned off when starting a core
275         sysexit