More debugging for VMs.
[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 <arch/x86.h>
11 #include <ros/memlayout.h>
12
13 ###################################################################
14 # exceptions/interrupts
15 ###################################################################
16
17 /* The TRAPHANDLER macro defines a globally-visible function for handling
18  * a trap.  It pushes a trap number onto the stack, then jumps to _alltraps.
19  * It also builds this traps portion of the trap_tbl.
20  * Use TRAPHANDLER for traps where the CPU automatically pushes an error code.
21  */
22 #define TRAPHANDLER(name, num)                                                                  \
23         .text;                                                                                                          \
24         .globl name;            /* define global symbol for 'name' */   \
25         .type name, @function;  /* symbol type is function */           \
26         .align 2;               /* align function definition */                         \
27         name:                   /* function starts here */                                      \
28         pushq $(num);                                                                                           \
29         jmp _alltraps;                                                                                          \
30         .data;                                                                                                          \
31         .quad name;                                                                                                     \
32         .long num
33
34 /* Use TRAPHANDLER_NOEC for traps where the CPU doesn't push an error code.
35  * It pushes a 0 in place of the error code, so the trap frame has the same
36  * format in either case.  */
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 /* 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         iretq;                                                          \
73         .data;                                                          \
74         .quad name;                                                     \
75         .long num
76
77 .data
78 .globl trap_tbl
79 trap_tbl:
80
81 /*
82  * Generate entry points for the different traps.
83  */
84 TRAPHANDLER_NOEC(ISR_divide_error, T_DIVIDE)
85 TRAPHANDLER_NOEC(ISR_debug_exceptions, T_DEBUG)
86 TRAPHANDLER_NOEC(ISR_NMI, T_NMI)
87 TRAPHANDLER_NOEC(ISR_breakpoint, T_BRKPT)
88 TRAPHANDLER_NOEC(ISR_overflow, T_OFLOW)
89 TRAPHANDLER_NOEC(ISR_bounds_check, T_BOUND)
90 TRAPHANDLER_NOEC(ISR_invalid_opcode, T_ILLOP)
91 TRAPHANDLER_NOEC(ISR_device_not_available, T_DEVICE)
92 /* supposedly, DF generates an error code, but the one time we've had a DF so
93  * far, it didn't.  eventually, this should probably be handled with a task gate
94  * it might have pushed a 0, but just the rest of the stack was corrupt
95  */
96 TRAPHANDLER_NOEC(ISR_double_fault, T_DBLFLT)
97 /* 9 reserved */
98 TRAPHANDLER(ISR_invalid_TSS, T_TSS)
99 TRAPHANDLER(ISR_segment_not_present, T_SEGNP)
100 TRAPHANDLER(ISR_stack_exception, T_STACK)
101 TRAPHANDLER(ISR_general_protection_fault, T_GPFLT)
102 TRAPHANDLER(ISR_page_fault, T_PGFLT)
103 /* 15 reserved */
104 TRAPHANDLER_NOEC(ISR_floating_point_error, T_FPERR)
105 TRAPHANDLER(ISR_alignment_check, T_ALIGN)
106 TRAPHANDLER_NOEC(ISR_machine_check, T_MCHK)
107 TRAPHANDLER_NOEC(ISR_simd_error, T_SIMDERR)
108 /* 20 - 31 reserved */
109 IRQ_HANDLER(IRQ0, 32)
110 IRQ_HANDLER(IRQ1, 33)
111 IRQ_HANDLER(IRQ2, 34)
112 IRQ_HANDLER(IRQ3, 35)
113 IRQ_HANDLER(IRQ4, 36)
114 IRQ_HANDLER(IRQ5, 37)
115 IRQ_HANDLER(IRQ6, 38)
116 IRQ_HANDLER(IRQ7, 39)
117 IRQ_HANDLER(IRQ8, 40)
118 IRQ_HANDLER(IRQ9, 41)
119 IRQ_HANDLER(IRQ10, 42)
120 IRQ_HANDLER(IRQ11, 43)
121 IRQ_HANDLER(IRQ12, 44)
122 IRQ_HANDLER(IRQ13, 45)
123 IRQ_HANDLER(IRQ14, 46)
124 IRQ_HANDLER(IRQ15, 47)
125 /* 25 general purpose vectors, for use by the LAPIC.  Can expand later. */
126 IRQ_HANDLER(IRQ198, I_TESTING) # used in testing.c
127 IRQ_HANDLER(IRQ199, 231)
128 IRQ_HANDLER(IRQ200, 232)
129 IRQ_HANDLER(IRQ201, 233)
130 IRQ_HANDLER(IRQ202, 234)
131 IRQ_HANDLER(IRQ203, 235)
132 IRQ_HANDLER(IRQ204, 236)
133 IRQ_HANDLER(IRQ205, 237)
134 IRQ_HANDLER(IRQ206, 238)
135 IRQ_HANDLER(IRQ207, 239)
136 /* 0xf0 - start of the SMP_CALL IPIS */
137 IRQ_HANDLER(IRQ208, I_SMP_CALL0)
138 IRQ_HANDLER(IRQ209, I_SMP_CALL1)
139 IRQ_HANDLER(IRQ210, I_SMP_CALL2)
140 IRQ_HANDLER(IRQ211, I_SMP_CALL3)
141 IRQ_HANDLER(IRQ212, I_SMP_CALL4)
142 IRQ_HANDLER(IRQ213, 245)
143 IRQ_HANDLER(IRQ214, 246)
144 IRQ_HANDLER(IRQ215, 247)
145 IRQ_HANDLER(IRQ216, 248)
146 IRQ_HANDLER(IRQ217, 249)
147 IRQ_HANDLER(IRQ218, 250)
148 IRQ_HANDLER(IRQ219, 251)
149 IRQ_HANDLER(IRQ220, 252)
150 IRQ_HANDLER(IRQ221, 253)
151 POKE_HANDLER(IRQ222, 254)
152 IRQ_HANDLER(IRQ223, I_KERNEL_MSG)
153
154 /* Technically, these HANDLER entries do not need to be in numeric order */
155 TRAPHANDLER_NOEC(ISR_syscall, T_SYSCALL)
156 /* But make sure default is last!! */
157 TRAPHANDLER_NOEC(ISR_default, T_DEFAULT)
158
159 .data
160 .globl trap_tbl_end
161 trap_tbl_end:
162
163 .text
164 _alltraps:
165         cld
166         swapgs                  # harmless if we were already in the kernel
167         pushq %r15
168         pushq %r14
169         pushq %r13
170         pushq %r12
171         pushq %r11
172         pushq %r10
173         pushq %r9
174         pushq %r8
175         pushq %rdi
176         pushq %rsi
177         pushq %rbp
178         pushq %rdx
179         pushq %rcx
180         pushq %rbx
181         pushq %rax
182         cmpw $GD_KT, 0x90(%rsp) # 0x90 - diff btw tf_cs and tf_rax
183         je trap_kernel_tf
184         # this is a user TF, so we need to save their fs/gsbase and load gs base for
185         # the kernel.
186         movl $MSR_FS_BASE, %ecx
187         rdmsr
188         shl $32, %rdx
189         orq %rax, %rdx
190         pushq %rdx
191         # because we swapped gs earlier, the user GS is now in KERN_GS_BASE
192         movl $MSR_KERN_GS_BASE, %ecx
193         rdmsr
194         shl $32, %rdx
195         orq %rax, %rdx
196         pushq %rdx
197         # make sure the kernel's gs base is loaded into the KERN slot at all times
198         movl $MSR_GS_BASE, %ecx
199         rdmsr
200         movl $MSR_KERN_GS_BASE, %ecx
201         wrmsr
202         jmp trap_all_tf
203 trap_kernel_tf:
204         # we don't muck with fs/gsbase, push placeholders
205         movq $0xdeadbeef, %rax
206         pushq %rax
207         pushq %rax
208 trap_all_tf:
209         movq $0, %rbp                   # so we can backtrace to this point
210         movq %rsp, %rdi
211         call trap
212         # the return paths are only used by the kernel
213         addq $0x10, %rsp                        # skip fs/gs base
214         popq %rax
215         popq %rbx
216         popq %rcx
217         popq %rdx
218         popq %rbp
219         popq %rsi
220         popq %rdi
221         popq %r8
222         popq %r9
223         popq %r10
224         popq %r11
225         popq %r12
226         popq %r13
227         popq %r14
228         popq %r15
229         addq $0x10, %rsp                        # skip trapno and err
230         iretq
231
232 # might merge this with _alltraps
233 _allirqs:
234         cld
235         swapgs                  # harmless if we were already in the kernel
236         pushq %r15
237         pushq %r14
238         pushq %r13
239         pushq %r12
240         pushq %r11
241         pushq %r10
242         pushq %r9
243         pushq %r8
244         pushq %rdi
245         pushq %rsi
246         pushq %rbp
247         pushq %rdx
248         pushq %rcx
249         pushq %rbx
250         pushq %rax
251         cmpw $GD_KT, 0x90(%rsp) # 0x90 - diff btw tf_cs and tf_rax
252         je irq_kernel_tf
253         # this is a user TF, so we need to save their fs/gsbase and load gs base for
254         # the kernel.
255         movl $MSR_FS_BASE, %ecx
256         rdmsr
257         shl $32, %rdx
258         orq %rax, %rdx
259         pushq %rdx
260         # because we swapped gs earlier, the user GS is now in KERN_GS_BASE
261         movl $MSR_KERN_GS_BASE, %ecx
262         rdmsr
263         shl $32, %rdx
264         orq %rax, %rdx
265         pushq %rdx
266         # make sure the kernel's gs base is loaded into the KERN slot at all times
267         movl $MSR_GS_BASE, %ecx
268         rdmsr
269         movl $MSR_KERN_GS_BASE, %ecx
270         wrmsr
271         jmp irq_all_tf
272 irq_kernel_tf:
273         # we don't muck with fs/gsbase, push placeholders
274         movq $0xdeadbeef, %rax
275         pushq %rax
276         pushq %rax
277 irq_all_tf:
278         movq $0, %rbp                   # so we can backtrace to this point
279         movq %rsp, %rdi
280         call handle_irq
281         # the return paths are only used by the kernel
282         addq $0x10, %rsp                        # skip fs/gs base
283         popq %rax
284         popq %rbx
285         popq %rcx
286         popq %rdx
287         popq %rbp
288         popq %rsi
289         popq %rdi
290         popq %r8
291         popq %r9
292         popq %r10
293         popq %r11
294         popq %r12
295         popq %r13
296         popq %r14
297         popq %r15
298         addq $0x10, %rsp                        # skip trapno and err
299         iretq
300
301 .globl sysenter_handler;
302 .type sysenter_handler, @function;
303
304 sysenter_handler:
305 #ifndef CONFIG_NOFASTCALL_FSBASE
306         # Do a quick TLS / FS base change, never changing stacks.
307         # When rdi has the magic number, rsi has the new base
308         movabs $FASTCALL_SETFSBASE, %rax
309         cmp %rax, %rdi
310         jne normal_syscall      # could profile this and handle the jump differently
311         # need to check rsi, make sure it is canonical (will enfore below ULIM).
312         # need to either do this check, or handle the kernel GP fault on wrmsr.
313         movq %rsi, %rdi
314         shrq $47, %rdi
315         cmp $0, %rdi
316         jne fastcall_pop
317         # need to use cx, dx, and ax for the wrmsr.  dx and ax are free.
318         movq %rcx, %rdi         # save rcx, the retaddr
319         movq %rsi, %rdx
320         movq %rsi, %rax
321         shrq $32, %rdx
322         andl $0xffffffff, %eax
323         movl $MSR_FS_BASE, %ecx
324         wrmsr
325         movq %rdi, %rcx         # restore retaddr
326 fastcall_pop:
327         rex.w sysret
328 normal_syscall:
329 #endif
330         # cld is handled by the SFMASK
331         swapgs
332         movq %gs:0, %rsp
333         # Saving the FPU callee-saved state for now.  Might be able to have the
334         # preempt handler deal with it.
335         pushq $0                        # space for mxcsr and fpucw
336         fnstcw 0x4(%rsp)
337         stmxcsr (%rsp)
338         pushq %rdx                      # rsp, saved by userspace
339         pushq %rcx                      # rip, saved by hardware
340         pushq %r15
341         pushq %r14
342         pushq %r13
343         pushq %r12
344         pushq %rbp
345         pushq %rbx
346         # save fs and gs base
347         movl $MSR_FS_BASE, %ecx
348         rdmsr
349         shl $32, %rdx
350         orq %rax, %rdx
351         pushq %rdx
352         # because we swapped gs earlier, the user GS is now in KERN_GS_BASE
353         movl $MSR_KERN_GS_BASE, %ecx
354         rdmsr
355         shl $32, %rdx
356         orq %rax, %rdx
357         pushq %rdx
358         # make sure the kernel's gs base is loaded into the KERN slot at all times
359         movl $MSR_GS_BASE, %ecx
360         rdmsr
361         movl $MSR_KERN_GS_BASE, %ecx
362         wrmsr
363         movq $0, %rbp                   # so we can backtrace to this point
364         movq %rsp, %rdx
365         # arg0, rdi: struct sysc*.  arg1, rsi: count.  arg2, rdx: sw_tf
366         call sysenter_callwrapper
367         # return via pop_tf, never this path
368 sysenter_spin:
369         jmp sysenter_spin