vmap: Use {map,unmap}_segment() helpers
[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 #define NMI_HANDLER(name, num)                  \
65         .text;                                                          \
66         .globl name;                                            \
67         .type name, @function;                          \
68         .align 2;                                                       \
69         name:                                                           \
70         pushq $0;                                                       \
71         pushq $(num);                                           \
72         jmp _nmi_entry;                                         \
73         .data;                                                          \
74         .quad name;                                                     \
75         .long num
76
77 /* Only used in the kernel during SMP boot.  Send a LAPIC_EOI and iret. */
78 #define POKE_HANDLER(name, num)                 \
79         .text;                                                          \
80         .globl name;                                            \
81         .type name, @function;                          \
82         .align 2;                                                       \
83         name:;                                                          \
84         pushq %rax;                     \
85         pushq %rcx;                     \
86         pushq %rdx;                     \
87         movq $0, %rax;                  \
88         movq $0, %rdx;                  \
89         movq $(MSR_LAPIC_EOI), %rcx;    \
90         wrmsr;                          \
91         popq %rdx;                      \
92         popq %rcx;                      \
93         popq %rax;                      \
94         iretq;                                                          \
95         .data;                                                          \
96         .quad name;                                                     \
97         .long num
98
99 # Set data for the trap_tbl symbol.  Set text for the entry_points.  The various
100 # trap/irq handler macros will toggle data on and off as needed.
101 .data
102 .globl trap_tbl
103 trap_tbl:
104 .text
105 .globl __asm_entry_points_start
106 __asm_entry_points_start:
107
108 /* Generate entry points for the different traps.  Note that all of these bounce
109  * off the corresponding trap.c function, such as handle_irqs, and that the name
110  * e.g. ISR_divide_error is soley for the little stup that jumps to something
111  * like _alltraps.
112  *
113  * Technically, these HANDLER entries do not need to be in numeric order.
114  * trap.c will do a 'foreach (up to last-1), set the IDT for the number to point
115  * to the func' in the order in which they appear in the trap tbl, so the 'last
116  * one wins'. */
117 TRAPHANDLER_NOEC(ISR_divide_error, T_DIVIDE)
118 TRAPHANDLER_NOEC(ISR_debug_exceptions, T_DEBUG)
119 NMI_HANDLER(ISR_NMI, T_NMI)
120 TRAPHANDLER_NOEC(ISR_breakpoint, T_BRKPT)
121 TRAPHANDLER_NOEC(ISR_overflow, T_OFLOW)
122 TRAPHANDLER_NOEC(ISR_bounds_check, T_BOUND)
123 TRAPHANDLER_NOEC(ISR_invalid_opcode, T_ILLOP)
124 TRAPHANDLER_NOEC(ISR_device_not_available, T_DEVICE)
125 /* supposedly, DF generates an error code, but the one time we've had a DF so
126  * far, it didn't.  eventually, this should probably be handled with a task gate
127  * it might have pushed a 0, but just the rest of the stack was corrupt
128  */
129 TRAPHANDLER_NOEC(ISR_double_fault, T_DBLFLT)
130 /* 9 reserved */
131 TRAPHANDLER(ISR_invalid_TSS, T_TSS)
132 TRAPHANDLER(ISR_segment_not_present, T_SEGNP)
133 TRAPHANDLER(ISR_stack_exception, T_STACK)
134 TRAPHANDLER(ISR_general_protection_fault, T_GPFLT)
135 TRAPHANDLER(ISR_page_fault, T_PGFLT)
136 /* 15 reserved */
137 TRAPHANDLER_NOEC(ISR_floating_point_error, T_FPERR)
138 TRAPHANDLER(ISR_alignment_check, T_ALIGN)
139 TRAPHANDLER_NOEC(ISR_machine_check, T_MCHK)
140 TRAPHANDLER_NOEC(ISR_simd_error, T_SIMDERR)
141 /* 20 - 31 reserved */
142 /* 32-47 are PIC/8259 IRQ vectors */
143 IRQ_HANDLER(IRQ0, 32)
144 IRQ_HANDLER(IRQ1, 33)
145 IRQ_HANDLER(IRQ2, 34)
146 IRQ_HANDLER(IRQ3, 35)
147 IRQ_HANDLER(IRQ4, 36)
148 IRQ_HANDLER(IRQ5, 37)
149 IRQ_HANDLER(IRQ6, 38)
150 IRQ_HANDLER(IRQ7, 39)
151 IRQ_HANDLER(IRQ8, 40)
152 IRQ_HANDLER(IRQ9, 41)
153 IRQ_HANDLER(IRQ10, 42)
154 IRQ_HANDLER(IRQ11, 43)
155 IRQ_HANDLER(IRQ12, 44)
156 IRQ_HANDLER(IRQ13, 45)
157 IRQ_HANDLER(IRQ14, 46)
158 IRQ_HANDLER(IRQ15, 47)
159 TRAPHANDLER_NOEC(ISR_syscall, T_SYSCALL)
160 /* 49-223 are IOAPIC routing vectors (from IOAPIC to LAPIC) */
161 IRQ_HANDLER(IRQ17, 49)
162 IRQ_HANDLER(IRQ18, 50)
163 IRQ_HANDLER(IRQ19, 51)
164 IRQ_HANDLER(IRQ20, 52)
165 IRQ_HANDLER(IRQ21, 53)
166 IRQ_HANDLER(IRQ22, 54)
167 IRQ_HANDLER(IRQ23, 55)
168 IRQ_HANDLER(IRQ24, 56)
169 IRQ_HANDLER(IRQ25, 57)
170 IRQ_HANDLER(IRQ26, 58)
171 IRQ_HANDLER(IRQ27, 59)
172 IRQ_HANDLER(IRQ28, 60)
173 IRQ_HANDLER(IRQ29, 61)
174 IRQ_HANDLER(IRQ30, 62)
175 IRQ_HANDLER(IRQ31, 63)
176 IRQ_HANDLER(IRQ32, 64)
177 IRQ_HANDLER(IRQ33, 65)
178 IRQ_HANDLER(IRQ34, 66)
179 IRQ_HANDLER(IRQ35, 67)
180 IRQ_HANDLER(IRQ36, 68)
181 IRQ_HANDLER(IRQ37, 69)
182 IRQ_HANDLER(IRQ38, 70)
183 IRQ_HANDLER(IRQ39, 71)
184 IRQ_HANDLER(IRQ40, 72)
185 IRQ_HANDLER(IRQ41, 73)
186 IRQ_HANDLER(IRQ42, 74)
187 IRQ_HANDLER(IRQ43, 75)
188 IRQ_HANDLER(IRQ44, 76)
189 IRQ_HANDLER(IRQ45, 77)
190 IRQ_HANDLER(IRQ46, 78)
191 IRQ_HANDLER(IRQ47, 79)
192 IRQ_HANDLER(IRQ48, 80)
193 IRQ_HANDLER(IRQ49, 81)
194 IRQ_HANDLER(IRQ50, 82)
195 IRQ_HANDLER(IRQ51, 83)
196 IRQ_HANDLER(IRQ52, 84)
197 IRQ_HANDLER(IRQ53, 85)
198 IRQ_HANDLER(IRQ54, 86)
199 IRQ_HANDLER(IRQ55, 87)
200 IRQ_HANDLER(IRQ56, 88)
201 IRQ_HANDLER(IRQ57, 89)
202 IRQ_HANDLER(IRQ58, 90)
203 IRQ_HANDLER(IRQ59, 91)
204 IRQ_HANDLER(IRQ60, 92)
205 IRQ_HANDLER(IRQ61, 93)
206 IRQ_HANDLER(IRQ62, 94)
207 IRQ_HANDLER(IRQ63, 95)
208 IRQ_HANDLER(IRQ64, 96)
209 IRQ_HANDLER(IRQ65, 97)
210 IRQ_HANDLER(IRQ66, 98)
211 IRQ_HANDLER(IRQ67, 99)
212 IRQ_HANDLER(IRQ68, 100)
213 IRQ_HANDLER(IRQ69, 101)
214 IRQ_HANDLER(IRQ70, 102)
215 IRQ_HANDLER(IRQ71, 103)
216 IRQ_HANDLER(IRQ72, 104)
217 IRQ_HANDLER(IRQ73, 105)
218 IRQ_HANDLER(IRQ74, 106)
219 IRQ_HANDLER(IRQ75, 107)
220 IRQ_HANDLER(IRQ76, 108)
221 IRQ_HANDLER(IRQ77, 109)
222 IRQ_HANDLER(IRQ78, 110)
223 IRQ_HANDLER(IRQ79, 111)
224 IRQ_HANDLER(IRQ80, 112)
225 IRQ_HANDLER(IRQ81, 113)
226 IRQ_HANDLER(IRQ82, 114)
227 IRQ_HANDLER(IRQ83, 115)
228 IRQ_HANDLER(IRQ84, 116)
229 IRQ_HANDLER(IRQ85, 117)
230 IRQ_HANDLER(IRQ86, 118)
231 IRQ_HANDLER(IRQ87, 119)
232 IRQ_HANDLER(IRQ88, 120)
233 IRQ_HANDLER(IRQ89, 121)
234 IRQ_HANDLER(IRQ90, 122)
235 IRQ_HANDLER(IRQ91, 123)
236 IRQ_HANDLER(IRQ92, 124)
237 IRQ_HANDLER(IRQ93, 125)
238 IRQ_HANDLER(IRQ94, 126)
239 IRQ_HANDLER(IRQ95, 127)
240 IRQ_HANDLER(IRQ96, 128)
241 IRQ_HANDLER(IRQ97, 129)
242 IRQ_HANDLER(IRQ98, 130)
243 IRQ_HANDLER(IRQ99, 131)
244 IRQ_HANDLER(IRQ100, 132)
245 IRQ_HANDLER(IRQ101, 133)
246 IRQ_HANDLER(IRQ102, 134)
247 IRQ_HANDLER(IRQ103, 135)
248 IRQ_HANDLER(IRQ104, 136)
249 IRQ_HANDLER(IRQ105, 137)
250 IRQ_HANDLER(IRQ106, 138)
251 IRQ_HANDLER(IRQ107, 139)
252 IRQ_HANDLER(IRQ108, 140)
253 IRQ_HANDLER(IRQ109, 141)
254 IRQ_HANDLER(IRQ110, 142)
255 IRQ_HANDLER(IRQ111, 143)
256 IRQ_HANDLER(IRQ112, 144)
257 IRQ_HANDLER(IRQ113, 145)
258 IRQ_HANDLER(IRQ114, 146)
259 IRQ_HANDLER(IRQ115, 147)
260 IRQ_HANDLER(IRQ116, 148)
261 IRQ_HANDLER(IRQ117, 149)
262 IRQ_HANDLER(IRQ118, 150)
263 IRQ_HANDLER(IRQ119, 151)
264 IRQ_HANDLER(IRQ120, 152)
265 IRQ_HANDLER(IRQ121, 153)
266 IRQ_HANDLER(IRQ122, 154)
267 IRQ_HANDLER(IRQ123, 155)
268 IRQ_HANDLER(IRQ124, 156)
269 IRQ_HANDLER(IRQ125, 157)
270 IRQ_HANDLER(IRQ126, 158)
271 IRQ_HANDLER(IRQ127, 159)
272 IRQ_HANDLER(IRQ128, 160)
273 IRQ_HANDLER(IRQ129, 161)
274 IRQ_HANDLER(IRQ130, 162)
275 IRQ_HANDLER(IRQ131, 163)
276 IRQ_HANDLER(IRQ132, 164)
277 IRQ_HANDLER(IRQ133, 165)
278 IRQ_HANDLER(IRQ134, 166)
279 IRQ_HANDLER(IRQ135, 167)
280 IRQ_HANDLER(IRQ136, 168)
281 IRQ_HANDLER(IRQ137, 169)
282 IRQ_HANDLER(IRQ138, 170)
283 IRQ_HANDLER(IRQ139, 171)
284 IRQ_HANDLER(IRQ140, 172)
285 IRQ_HANDLER(IRQ141, 173)
286 IRQ_HANDLER(IRQ142, 174)
287 IRQ_HANDLER(IRQ143, 175)
288 IRQ_HANDLER(IRQ144, 176)
289 IRQ_HANDLER(IRQ145, 177)
290 IRQ_HANDLER(IRQ146, 178)
291 IRQ_HANDLER(IRQ147, 179)
292 IRQ_HANDLER(IRQ148, 180)
293 IRQ_HANDLER(IRQ149, 181)
294 IRQ_HANDLER(IRQ150, 182)
295 IRQ_HANDLER(IRQ151, 183)
296 IRQ_HANDLER(IRQ152, 184)
297 IRQ_HANDLER(IRQ153, 185)
298 IRQ_HANDLER(IRQ154, 186)
299 IRQ_HANDLER(IRQ155, 187)
300 IRQ_HANDLER(IRQ156, 188)
301 IRQ_HANDLER(IRQ157, 189)
302 IRQ_HANDLER(IRQ158, 190)
303 IRQ_HANDLER(IRQ159, 191)
304 IRQ_HANDLER(IRQ160, 192)
305 IRQ_HANDLER(IRQ161, 193)
306 IRQ_HANDLER(IRQ162, 194)
307 IRQ_HANDLER(IRQ163, 195)
308 IRQ_HANDLER(IRQ164, 196)
309 IRQ_HANDLER(IRQ165, 197)
310 IRQ_HANDLER(IRQ166, 198)
311 IRQ_HANDLER(IRQ167, 199)
312 IRQ_HANDLER(IRQ168, 200)
313 IRQ_HANDLER(IRQ169, 201)
314 IRQ_HANDLER(IRQ170, 202)
315 IRQ_HANDLER(IRQ171, 203)
316 IRQ_HANDLER(IRQ172, 204)
317 IRQ_HANDLER(IRQ173, 205)
318 IRQ_HANDLER(IRQ174, 206)
319 IRQ_HANDLER(IRQ175, 207)
320 IRQ_HANDLER(IRQ176, 208)
321 IRQ_HANDLER(IRQ177, 209)
322 IRQ_HANDLER(IRQ178, 210)
323 IRQ_HANDLER(IRQ179, 211)
324 IRQ_HANDLER(IRQ180, 212)
325 IRQ_HANDLER(IRQ181, 213)
326 IRQ_HANDLER(IRQ182, 214)
327 IRQ_HANDLER(IRQ183, 215)
328 IRQ_HANDLER(IRQ184, 216)
329 IRQ_HANDLER(IRQ185, 217)
330 IRQ_HANDLER(IRQ186, 218)
331 IRQ_HANDLER(IRQ187, 219)
332 IRQ_HANDLER(IRQ188, 220)
333 IRQ_HANDLER(IRQ189, 221)
334 IRQ_HANDLER(IRQ190, 222)
335 IRQ_HANDLER(IRQ191, 223)
336 /* 224-239 are OS IPI vectors (0xe0-0xef) */
337 IRQ_HANDLER(IRQ192, I_SMP_CALL0)
338 IRQ_HANDLER(IRQ193, I_SMP_CALL1)
339 IRQ_HANDLER(IRQ194, I_SMP_CALL2)
340 IRQ_HANDLER(IRQ195, I_SMP_CALL3)
341 IRQ_HANDLER(IRQ196, I_SMP_CALL4)
342 IRQ_HANDLER(IRQ197, 229)
343 IRQ_HANDLER(IRQ198, 230)
344 IRQ_HANDLER(IRQ199, 231)
345 IRQ_HANDLER(IRQ200, 232)
346 IRQ_HANDLER(IRQ201, 233)
347 IRQ_HANDLER(IRQ202, 234)
348 IRQ_HANDLER(IRQ203, 235)
349 IRQ_HANDLER(IRQ204, 236)
350 IRQ_HANDLER(IRQ205, I_TESTING)
351 POKE_HANDLER(IRQ206, I_POKE_CORE)
352 IRQ_HANDLER(IRQ207, I_KERNEL_MSG)
353 /* 240-255 are LAPIC vectors (0xf0-0xff), hightest priority class */
354 IRQ_HANDLER(IRQ208, 240)
355 IRQ_HANDLER(IRQ209, 241)
356 IRQ_HANDLER(IRQ210, 242)
357 IRQ_HANDLER(IRQ211, 243)
358 IRQ_HANDLER(IRQ212, 244)
359 IRQ_HANDLER(IRQ213, 245)
360 IRQ_HANDLER(IRQ214, 246)
361 IRQ_HANDLER(IRQ215, 247)
362 IRQ_HANDLER(IRQ216, 248)
363 IRQ_HANDLER(IRQ217, 249)
364 IRQ_HANDLER(IRQ218, 250)
365 IRQ_HANDLER(IRQ219, 251)
366 IRQ_HANDLER(IRQ220, 252)
367 IRQ_HANDLER(IRQ221, 253)
368 IRQ_HANDLER(IRQ222, 254)
369 IRQ_HANDLER(IRQ223, 255)
370 /* But make sure default is last!! */
371 TRAPHANDLER_NOEC(ISR_default, T_DEFAULT)
372
373 .data
374 .globl trap_tbl_end
375 trap_tbl_end:
376
377 .text
378 _alltraps:
379         cld
380         pushq %r15
381         pushq %r14
382         pushq %r13
383         pushq %r12
384         pushq %r11
385         pushq %r10
386         pushq %r9
387         pushq %r8
388         pushq %rdi
389         pushq %rsi
390         pushq %rbp
391         pushq %rdx
392         pushq %rcx
393         pushq %rbx
394         pushq %rax
395         cmpw $GD_KT, 0x90(%rsp) # 0x90 - diff btw tf_cs and tf_rax
396         je trap_all_tf
397         # this is a user TF.  we need to swapgs to get the kernel's gs and mark the
398         # context as partial
399         swapgs                                  # user's GS is now in MSR_KERNEL_GS_BASE
400         movl $0x1, 0xac(%rsp)   # 0xac - diff btw tf_padding0 and tf_rax
401 trap_all_tf:
402         pushq $0                                # fsbase space
403         pushq $0                                # gsbase space
404         movq $0, %rbp                   # so we can backtrace to this point
405         movq %rsp, %rdi
406         call trap
407         # the return paths are only used by the kernel
408         addq $0x10, %rsp                        # skip fs/gs base
409         popq %rax
410         popq %rbx
411         popq %rcx
412         popq %rdx
413         popq %rbp
414         popq %rsi
415         popq %rdi
416         popq %r8
417         popq %r9
418         popq %r10
419         popq %r11
420         popq %r12
421         popq %r13
422         popq %r14
423         popq %r15
424         addq $0x10, %rsp                        # skip trapno and err
425         iretq
426
427 # might merge this with _alltraps
428 _allirqs:
429         cld
430         pushq %r15
431         pushq %r14
432         pushq %r13
433         pushq %r12
434         pushq %r11
435         pushq %r10
436         pushq %r9
437         pushq %r8
438         pushq %rdi
439         pushq %rsi
440         pushq %rbp
441         pushq %rdx
442         pushq %rcx
443         pushq %rbx
444         pushq %rax
445         cmpw $GD_KT, 0x90(%rsp) # 0x90 - diff btw tf_cs and tf_rax
446         je irq_all_tf
447         # this is a user TF.  we need to swapgs to get the kernel's gs and mark the
448         # context as partial
449         swapgs                                  # user's GS is now in MSR_KERNEL_GS_BASE
450         movl $0x1, 0xac(%rsp)   # 0xac - diff btw tf_padding0 and tf_rax
451 irq_all_tf:
452         pushq $0                                # fsbase space
453         pushq $0                                # gsbase space
454         movq $0, %rbp                   # so we can backtrace to this point
455         movq %rsp, %rdi
456         call handle_irq
457         # the return paths are only used by the kernel
458         addq $0x10, %rsp                        # skip fs/gs base
459         popq %rax
460         popq %rbx
461         popq %rcx
462         popq %rdx
463         popq %rbp
464         popq %rsi
465         popq %rdi
466         popq %r8
467         popq %r9
468         popq %r10
469         popq %r11
470         popq %r12
471         popq %r13
472         popq %r14
473         popq %r15
474         addq $0x10, %rsp                        # skip trapno and err
475         iretq
476
477 # Unlike normal trap and IRQ handlers, both user and kernel TFs are handled the
478 # similarly.  Both come in here and return from here.  We cannot do anything
479 # fancy like proc_restartcore() from NMI context.
480 #
481 # All NMIs will come in fresh on the same stack (IST1, per-core).  We don't need
482 # to find a stackpointer, but we do need to find GS.
483 #
484 # Regardless of whether or not the interrupted context was in the kernel, we
485 # can't trust GS.  Basically we can never tell from looking at GS and KERN_GS
486 # whether swapgs occurred, since the user could have put kernel addrs in their
487 # GS.  But we can use the stack for storage to bootstrap GS.  %rsp at entry
488 # points to pcpui *.
489 #
490 # We can also tell if GS was set correctly or not and avoid the wrmsr calls.
491 # This isn't a huge deal.  But note that we don't know whether or not the kernel
492 # actually set the gsbase.  We just know if it was correct or not.  The user
493 # could have set it and the kernel hadn't had a chance to swapgs yet.  The NMI
494 # handler doesn't care, since all TFs come in and go out via this asm.
495 #
496 # If we want to be paranoid, we can completely ignore user TFs and just save and
497 # restore GS with the same mechanism we use for the kernel.  But since we came
498 # in on a user TF, we can use swapgs.  Note that even for nested NMI handlers,
499 # we have a user TF for only the first time, and only the last exit will swapgs
500 # back to the way it was initially.
501 _nmi_entry:
502         cld
503         pushq %r15
504         pushq %r14
505         pushq %r13
506         pushq %r12
507         pushq %r11
508         pushq %r10
509         pushq %r9
510         pushq %r8
511         pushq %rdi
512         pushq %rsi
513         pushq %rbp
514         pushq %rdx
515         pushq %rcx
516         pushq %rbx
517         pushq %rax
518         cmpw $GD_KT, 0x90(%rsp) # 0x90 - diff btw tf_cs and tf_rax
519         je nmi_kern_tf
520         # this is a user TF.  we need to swapgs to get the kernel's gs and mark the
521         # context as partial
522         swapgs                                  # user's GS is now in MSR_KERNEL_GS_BASE
523         movl $0x1, 0xac(%rsp)   # 0xac - diff btw tf_padding0 and tf_rax
524         pushq $0                                # fsbase space
525         pushq $0                                # gsbase space
526         jmp nmi_all_tf
527 nmi_kern_tf:
528         # this is a kernel TF.  but we don't know if they set up gs yet, so we'll
529         # save and restore whatever they had loaded and use our own
530         pushq $0                                # fsbase space
531         # Get the current GS base into rax
532         movl $MSR_GS_BASE, %ecx
533         rdmsr
534         shlq $32, %rdx
535         orq %rdx, %rax
536         # Get the real GS base from the top of the stack.  This was set in smp_boot,
537         # and our rsp pointed to it when we entered the kernel.
538         movq 0xb8(%rsp), %rdx   # 0xb8 from fs_base to the top
539         # Compare them.  If they are the same, we can just push 0 for gsbase (which
540         # later will mean "no need to restore GS".
541         cmpq %rdx, %rax
542         je nmi_gs_ok
543         # They weren't the same.  Save the old one and set the new one.
544         pushq %rax                              # gsbase space
545         movq %rdx, %rax
546         shrq $32, %rdx
547         andl $0xffffffff, %eax
548         wrmsr
549         jmp nmi_all_tf
550 nmi_gs_ok:
551         pushq $0                                # gsbase space
552 nmi_all_tf:
553         # At this point, GS is set correctly, either due to swapgs (user TF), wrmsr
554         # (kern TF with bad GS), or it was already fine (and gsbase in the TF = 0).
555         movq $0, %rbp                   # so we can backtrace to this point
556         movq %rsp, %rdi
557         call handle_nmi
558         # Unlike in normal IRQs/Traps, both user and kernel contexts return via this
559         # path.
560         cmpw $GD_KT, 0xa0(%rsp) # 0xa0 - diff btw tf_cs and tf_gsbase
561         je nmi_kern_restore_gs
562         # User TF.  Restore whatever was there with swapgs.  We don't care what it
563         # was, nor do we care what was in the TF.
564         swapgs                                  # user's GS is now in MSR_GS_BASE
565         addq $0x10, %rsp                # skip gs/fs base
566         jmp nmi_popal
567 nmi_kern_restore_gs:
568         popq %rax                               # fetch saved gsbase
569         addq $0x08, %rsp                # skip fs base
570         cmpq $0, %rax
571         je nmi_popal
572         # gsbase in the TF != 0, which means we need to restore that gsbase
573         movl $MSR_GS_BASE, %ecx
574         movq %rax, %rdx
575         shrq $32, %rdx
576         andl $0xffffffff, %eax
577         wrmsr
578 nmi_popal:
579         popq %rax
580         popq %rbx
581         popq %rcx
582         popq %rdx
583         popq %rbp
584         popq %rsi
585         popq %rdi
586         popq %r8
587         popq %r9
588         popq %r10
589         popq %r11
590         popq %r12
591         popq %r13
592         popq %r14
593         popq %r15
594         addq $0x10, %rsp                        # skip trapno and err
595         iretq
596
597 .globl __nmi_pop_ok_start;
598 .globl __nmi_pop_ok_end;
599 .globl __nmi_pop_fail_start;
600 .globl __nmi_pop_fail_end;
601
602 # extern void nmi_try_to_pop(struct hw_trapframe *tf, int *status,
603 #                            int old_val, int new_val);
604 #
605 # __nmi_bottom_half calls this to atomically pop a hw_tf (%rdi) and set
606 # &pcpui->nmi_status (%rsi) with compare and swap to NMI_NORMAL_OPN (%ecx) given
607 # that it was NMI_IN_PROGRESS (%edx)
608 #
609 # (Careful, nmi_status is an int, not a long.)
610 #
611 # If the real NMI handler interrupts us, it'll move us to the fail section of
612 # the code.  That code is identical to 'ok', up until ok's final statement.
613 #
614 # In that event, we'll need a little help returning: specifically to bootstrap
615 # pcpui and our current stackpointer.  pcpui is already saved near the top of
616 # stack.  We'll save rsp ourselves.
617 .globl nmi_try_to_pop;
618 .type nmi_try_to_pop, @function;
619 nmi_try_to_pop:
620 __nmi_pop_ok_start:
621         # careful only to use caller-saved or argument registers before saving
622         movl %edx, %eax                 # load old_val into eax for the CAS
623         cmpxchgl %ecx, (%rsi)   # no need for LOCK, since an NMI would serialize
624         jz nmi_ok_cas_worked    # ZF = 1 on successful CAS
625         ret
626 nmi_ok_cas_worked:
627         # save callee-saved regs (the pops below clobber them, and we might return)
628         pushq %rbp
629         pushq %rbx
630         pushq %r12
631         pushq %r13
632         pushq %r14
633         pushq %r15
634         # We need to save the current rsp into the scratch space at the top of the
635         # stack.  This assumes we're within the top page of our stack, which should
636         # always be true.  Careful not to use rdi, which still has an argument.
637         movq %rsp, %rbx
638         # Want to round rbx up to PGSIZE, then subtract 8, to get our slot.
639         movq $0xfff, %rax
640         notq %rax                               # rax = 0xfffffffffffff000
641         andq %rax, %rbx                 # round down rbx
642         addq $0x1000, %rbx              # add PGSIZE, assuming rsp was not page aligned
643         subq $0x8, %rbx                 # point to the scratch space
644         movq %rsp, (%rbx)               # save rsp in the scratch space
645         # We jump our rsp to the base of the HW_TF.  This is still on the same
646         # stack, just farther back than where our caller is.  We need to be careful
647         # to not clobber the stack.  Otherwise we'll have chaos.
648         movq %rdi, %rsp
649         # From here down is the same as the normal NMI exit path, but with 'ok' in
650         # the symbol names.
651         cmpw $GD_KT, 0xa0(%rsp) # 0xa0 - diff btw tf_cs and tf_gsbase
652         je nmi_ok_kern_restore_gs
653         # User TF.  Restore whatever was there with swapgs.  We don't care what it
654         # was, nor do we care what was in the TF.
655         swapgs                                  # user's GS is now in MSR_GS_BASE
656         addq $0x10, %rsp                # skip gs/fs base
657         jmp nmi_ok_popal
658 nmi_ok_kern_restore_gs:
659         popq %rax                               # fetch saved gsbase
660         addq $0x08, %rsp                # skip fs base
661         cmpq $0, %rax
662         je nmi_ok_popal
663         # gsbase in the TF != 0, which means we need to restore that gsbase
664         movl $MSR_GS_BASE, %ecx
665         movq %rax, %rdx
666         shrq $32, %rdx
667         andl $0xffffffff, %eax
668         wrmsr
669 nmi_ok_popal:
670         popq %rax
671         popq %rbx
672         popq %rcx
673         popq %rdx
674         popq %rbp
675         popq %rsi
676         popq %rdi
677         popq %r8
678         popq %r9
679         popq %r10
680         popq %r11
681         popq %r12
682         popq %r13
683         popq %r14
684         popq %r15
685         addq $0x10, %rsp                        # skip trapno and err
686         iretq
687 __nmi_pop_ok_end:
688
689 # This is the 'fail' case.  It is identical to the 'ok' case, up until the
690 # iretq, other than 'ok' replaced with 'fail'.  In place of iretq, we undo the
691 # entire operation.
692 __nmi_pop_fail_start:
693         # careful only to use caller-saved or argument registers before saving
694         movl %edx, %eax                 # load old_val into eax for the CAS
695         cmpxchgl %ecx, (%rsi)   # no need for LOCK, since an NMI would serialize
696         jz nmi_fail_cas_worked  # ZF = 1 on successful CAS
697         ret
698 nmi_fail_cas_worked:
699         # save callee-saved regs (the pops below clobber them, and we might return)
700         pushq %rbp
701         pushq %rbx
702         pushq %r12
703         pushq %r13
704         pushq %r14
705         pushq %r15
706         # We need to save the current rsp into the scratch space at the top of the
707         # stack.  This assumes we're within the top page of our stack, which should
708         # always be true.  Careful not to use rdi, which still has an argument.
709         movq %rsp, %rbx
710         # Want to round rbx up to PGSIZE, then subtract 8, to get our slot.
711         movq $0xfff, %rax
712         notq %rax                               # rax = 0xfffffffffffff000
713         andq %rax, %rbx                 # round down rbx
714         addq $0x1000, %rbx              # add PGSIZE, assuming rsp was not page aligned
715         subq $0x8, %rbx                 # point to the scratch space
716         movq %rsp, (%rbx)               # save rsp in the scratch space
717         # We jump our rsp to the base of the HW_TF.  This is still on the same
718         # stack, just farther back than where our caller is.  We need to be careful
719         # to not clobber the stack.  Otherwise we'll have chaos.
720         movq %rdi, %rsp
721         # From here down is the same as the normal NMI exit path and the ok path,
722         # but with 'fail' in the symbol names.
723         cmpw $GD_KT, 0xa0(%rsp) # 0xa0 - diff btw tf_cs and tf_gsbase
724         je nmi_fail_kern_restore_gs
725         # User TF.  Restore whatever was there with swapgs.  We don't care what it
726         # was, nor do we care what was in the TF.
727         swapgs                                  # user's GS is now in MSR_GS_BASE
728         addq $0x10, %rsp                # skip gs/fs base
729         jmp nmi_fail_popal
730 nmi_fail_kern_restore_gs:
731         popq %rax                               # fetch saved gsbase
732         addq $0x08, %rsp                # skip fs base
733         cmpq $0, %rax
734         je nmi_fail_popal
735         # gsbase in the TF != 0, which means we need to restore that gsbase
736         movl $MSR_GS_BASE, %ecx
737         movq %rax, %rdx
738         shrq $32, %rdx
739         andl $0xffffffff, %eax
740         wrmsr
741 nmi_fail_popal:
742         popq %rax
743         popq %rbx
744         popq %rcx
745         popq %rdx
746         popq %rbp
747         popq %rsi
748         popq %rdi
749         popq %r8
750         popq %r9
751         popq %r10
752         popq %r11
753         popq %r12
754         popq %r13
755         popq %r14
756         popq %r15
757         addq $0x10, %rsp                # skip trapno and err
758         # Here's is where we differ from OK.  Time to undo everything and return
759         # rsp currently is pointing at tf->tf_rip.  Remember that we don't want to
760         # write anything to the stack - everything in the TF is still the way it was
761         # when we started to pop.
762         #
763         # First off, let's get the stack addr of the pcpui pointer loaded
764         movq %rsp, %rbx
765         movq $0xfff, %rax
766         notq %rax                               # rax = 0xfffffffffffff000
767         andq %rax, %rbx                 # round down rbx
768         addq $0x1000, %rbx              # add PGSIZE, assuming rsp was not page aligned
769         subq $0x10, %rbx                # point to the pcpui pointer
770         # Now let's start to unwind
771         subq $0x98, %rsp                # jump from rip to tf_gsbase (top of hw_tf)
772         # Need to restore gs, just like on an NMI entry
773         cmpw $GD_KT, 0xa0(%rsp) # 0xa0 - diff btw tf_cs and tf_gsbase
774         je nmi_pop_fail_kern_tf
775         # This is a user TF.  We need to swapgs to get the kernel's gs
776         # We don't need to mark the context as partial (we never do for NMIs,
777         # actually), and in general, we don't want to write anything on the stack.
778         swapgs                                  # user's GS is now in MSR_KERNEL_GS_BASE
779         jmp nmi_pop_fail_all_tf
780 nmi_pop_fail_kern_tf:
781         # Kernel TF.  We basically need to do the same thing on entry, since we
782         # might have restored some weird GS base.  We can tell based on tf_gsbase
783         # 0 for gsbase means we didn't need to change GS
784         cmpq $0, (%rsp)
785         je nmi_pop_fail_gs_fine
786         # rbx points to where pcpui* is stored
787         mov (%rbx), %rdx
788         movl $MSR_GS_BASE, %ecx
789         movq %rdx, %rax
790         shrq $32, %rdx
791         andl $0xffffffff, %eax
792         wrmsr
793 nmi_pop_fail_gs_fine:
794 nmi_pop_fail_all_tf:
795         addq $0x8, %rbx                 # move to the scratch slot, holding rsp
796         mov (%rbx), %rsp
797         # restore callee-saved regs
798         popq %r15
799         popq %r14
800         popq %r13
801         popq %r12
802         popq %rbx
803         popq %rbp
804         ret
805         # sweet jeebus.
806 __nmi_pop_fail_end:
807
808
809 .globl sysenter_handler;
810 .type sysenter_handler, @function;
811
812 sysenter_handler:
813 #ifndef CONFIG_NOFASTCALL_FSBASE
814         # Do a quick TLS / FS base change, never changing stacks.
815         # When rdi has the magic number, rsi has the new base
816         movabs $FASTCALL_SETFSBASE, %rax
817         cmp %rax, %rdi
818         jne normal_syscall      # could profile this and handle the jump differently
819         # need to check rsi, make sure it is canonical (will enfore below ULIM).
820         # need to either do this check, or handle the kernel GP fault on wrmsr.
821         movq %rsi, %rdi
822         shrq $47, %rdi
823         cmp $0, %rdi
824         jne fastcall_pop
825         # need to use cx, dx, and ax for the wrmsr.  dx and ax are free.
826         movq %rcx, %rdi         # save rcx, the retaddr
827         movq %rsi, %rdx
828         movq %rsi, %rax
829         shrq $32, %rdx
830         andl $0xffffffff, %eax
831         movl $MSR_FS_BASE, %ecx
832         wrmsr
833         movq %rdi, %rcx         # restore retaddr
834 fastcall_pop:
835         rex.w sysret
836 normal_syscall:
837 #endif
838         # cld is handled by the SFMASK
839         swapgs                                  # user's GS is now in MSR_KERNEL_GS_BASE
840         movq %gs:0, %rsp
841         # Saving the FPU callee-saved state for now.  Might be able to have the
842         # preempt handler deal with it.
843         pushq $0                                # space for mxcsr, fpucw, and padding0
844         movw $0x1, 0x6(%rsp)    # tf_padding0 = 1, partial context
845         fnstcw 0x4(%rsp)
846         stmxcsr (%rsp)
847         pushq %rdx                      # rsp, saved by userspace
848         pushq %rcx                      # rip, saved by hardware
849         pushq %r15
850         pushq %r14
851         pushq %r13
852         pushq %r12
853         pushq %rbp
854         pushq %rbx
855         pushq $0                        # fsbase space
856         pushq $0                        # gsbase space
857         movq $0, %rbp                   # so we can backtrace to this point
858         movq %rsp, %rdx
859         # arg0, rdi: struct sysc*.  arg1, rsi: count.  arg2, rdx: sw_tf
860         call sysenter_callwrapper
861         # return via pop_tf, never this path
862 sysenter_spin:
863         jmp sysenter_spin
864
865 .globl vmexit_handler;
866 .type vmexit_handler, @function;
867 vmexit_handler:
868         # rflags has all flags = 0, so cli and cld already.
869         # HOST_GS_BASE and RSP is set by the hardware
870         # Set default values.  Most of these will be set in C later.
871         pushq $0                        # guest_pa
872         pushq $0                        # guest_va
873         pushq $0                        # intrinfo2 and 1
874         pushq $0                        # exit_qual + exit_reason
875         pushq $0                        # pad + trap_inject
876         pushq $0                        # flags + guest_pcorid
877         pushq $0                        # cr3
878         pushq $0                        # cr2
879         pushq $0                        # rsp
880         pushq $0                        # rflags
881         pushq $0                        # rip
882         # Save register state
883         pushq %r15
884         pushq %r14
885         pushq %r13
886         pushq %r12
887         pushq %r11
888         pushq %r10
889         pushq %r9
890         pushq %r8
891         pushq %rdi
892         pushq %rsi
893         pushq %rbp
894         pushq %rdx
895         pushq %rcx
896         pushq %rbx
897         pushq %rax
898         movq $0, %rbp                   # so we can backtrace to this point
899         movq %rsp, %rdi
900         call handle_vmexit
901 vmexit_spin:
902         jmp vmexit_spin
903
904 .globl __asm_entry_points_end
905 __asm_entry_points_end: