MSI cleanup and IRQ routing
[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 /* IOAPIC/MSI vectors */
126 IRQ_HANDLER(IRQ16, 48)
127 IRQ_HANDLER(IRQ17, 49)
128 IRQ_HANDLER(IRQ18, 50)
129 IRQ_HANDLER(IRQ19, 51)
130 IRQ_HANDLER(IRQ20, 52)
131 IRQ_HANDLER(IRQ21, 53)
132 IRQ_HANDLER(IRQ22, 54)
133 IRQ_HANDLER(IRQ23, 55)
134 IRQ_HANDLER(IRQ24, 56)
135 IRQ_HANDLER(IRQ25, 57)
136 IRQ_HANDLER(IRQ26, 58)
137 IRQ_HANDLER(IRQ27, 59)
138 IRQ_HANDLER(IRQ28, 60)
139 IRQ_HANDLER(IRQ29, 61)
140 IRQ_HANDLER(IRQ30, 62)
141 IRQ_HANDLER(IRQ31, 63)
142 IRQ_HANDLER(IRQ32, 64)
143 IRQ_HANDLER(IRQ33, 65)
144 IRQ_HANDLER(IRQ34, 66)
145 IRQ_HANDLER(IRQ35, 67)
146 IRQ_HANDLER(IRQ36, 68)
147 IRQ_HANDLER(IRQ37, 69)
148 IRQ_HANDLER(IRQ38, 70)
149 IRQ_HANDLER(IRQ39, 71)
150 IRQ_HANDLER(IRQ40, 72)
151 IRQ_HANDLER(IRQ41, 73)
152 IRQ_HANDLER(IRQ42, 74)
153 IRQ_HANDLER(IRQ43, 75)
154 IRQ_HANDLER(IRQ44, 76)
155 IRQ_HANDLER(IRQ45, 77)
156 IRQ_HANDLER(IRQ46, 78)
157 IRQ_HANDLER(IRQ47, 79)
158 IRQ_HANDLER(IRQ48, 80)
159 IRQ_HANDLER(IRQ49, 81)
160 IRQ_HANDLER(IRQ50, 82)
161 IRQ_HANDLER(IRQ51, 83)
162 IRQ_HANDLER(IRQ52, 84)
163 IRQ_HANDLER(IRQ53, 85)
164 IRQ_HANDLER(IRQ54, 86)
165 IRQ_HANDLER(IRQ55, 87)
166 IRQ_HANDLER(IRQ56, 88)
167 IRQ_HANDLER(IRQ57, 89)
168 IRQ_HANDLER(IRQ58, 90)
169 IRQ_HANDLER(IRQ59, 91)
170 IRQ_HANDLER(IRQ60, 92)
171 IRQ_HANDLER(IRQ61, 93)
172 IRQ_HANDLER(IRQ62, 94)
173 IRQ_HANDLER(IRQ63, 95)
174 IRQ_HANDLER(IRQ64, 96)
175 IRQ_HANDLER(IRQ65, 97)
176 IRQ_HANDLER(IRQ66, 98)
177 IRQ_HANDLER(IRQ67, 99)
178 IRQ_HANDLER(IRQ68, 100)
179 IRQ_HANDLER(IRQ69, 101)
180 IRQ_HANDLER(IRQ70, 102)
181 IRQ_HANDLER(IRQ71, 103)
182 IRQ_HANDLER(IRQ72, 104)
183 IRQ_HANDLER(IRQ73, 105)
184 IRQ_HANDLER(IRQ74, 106)
185 IRQ_HANDLER(IRQ75, 107)
186 IRQ_HANDLER(IRQ76, 108)
187 IRQ_HANDLER(IRQ77, 109)
188 IRQ_HANDLER(IRQ78, 110)
189 IRQ_HANDLER(IRQ79, 111)
190 IRQ_HANDLER(IRQ80, 112)
191 IRQ_HANDLER(IRQ81, 113)
192 IRQ_HANDLER(IRQ82, 114)
193 IRQ_HANDLER(IRQ83, 115)
194 IRQ_HANDLER(IRQ84, 116)
195 IRQ_HANDLER(IRQ85, 117)
196 IRQ_HANDLER(IRQ86, 118)
197 IRQ_HANDLER(IRQ87, 119)
198 IRQ_HANDLER(IRQ88, 120)
199 IRQ_HANDLER(IRQ89, 121)
200 IRQ_HANDLER(IRQ90, 122)
201 IRQ_HANDLER(IRQ91, 123)
202 IRQ_HANDLER(IRQ92, 124)
203 IRQ_HANDLER(IRQ93, 125)
204 IRQ_HANDLER(IRQ94, 126)
205 IRQ_HANDLER(IRQ95, 127)
206 IRQ_HANDLER(IRQ96, 128)
207 IRQ_HANDLER(IRQ97, 129)
208 IRQ_HANDLER(IRQ98, 130)
209 IRQ_HANDLER(IRQ99, 131)
210 IRQ_HANDLER(IRQ100, 132)
211 IRQ_HANDLER(IRQ101, 133)
212 IRQ_HANDLER(IRQ102, 134)
213 IRQ_HANDLER(IRQ103, 135)
214 IRQ_HANDLER(IRQ104, 136)
215 IRQ_HANDLER(IRQ105, 137)
216 IRQ_HANDLER(IRQ106, 138)
217 IRQ_HANDLER(IRQ107, 139)
218 IRQ_HANDLER(IRQ108, 140)
219 IRQ_HANDLER(IRQ109, 141)
220 IRQ_HANDLER(IRQ110, 142)
221 IRQ_HANDLER(IRQ111, 143)
222 IRQ_HANDLER(IRQ112, 144)
223 IRQ_HANDLER(IRQ113, 145)
224 IRQ_HANDLER(IRQ114, 146)
225 IRQ_HANDLER(IRQ115, 147)
226 IRQ_HANDLER(IRQ116, 148)
227 IRQ_HANDLER(IRQ117, 149)
228 IRQ_HANDLER(IRQ118, 150)
229 IRQ_HANDLER(IRQ119, 151)
230 IRQ_HANDLER(IRQ120, 152)
231 IRQ_HANDLER(IRQ121, 153)
232 IRQ_HANDLER(IRQ122, 154)
233 IRQ_HANDLER(IRQ123, 155)
234 IRQ_HANDLER(IRQ124, 156)
235 IRQ_HANDLER(IRQ125, 157)
236 IRQ_HANDLER(IRQ126, 158)
237 IRQ_HANDLER(IRQ127, 159)
238 IRQ_HANDLER(IRQ128, 160)
239 IRQ_HANDLER(IRQ129, 161)
240 IRQ_HANDLER(IRQ130, 162)
241 IRQ_HANDLER(IRQ131, 163)
242 IRQ_HANDLER(IRQ132, 164)
243 IRQ_HANDLER(IRQ133, 165)
244 IRQ_HANDLER(IRQ134, 166)
245 IRQ_HANDLER(IRQ135, 167)
246 IRQ_HANDLER(IRQ136, 168)
247 IRQ_HANDLER(IRQ137, 169)
248 IRQ_HANDLER(IRQ138, 170)
249 IRQ_HANDLER(IRQ139, 171)
250 IRQ_HANDLER(IRQ140, 172)
251 IRQ_HANDLER(IRQ141, 173)
252 IRQ_HANDLER(IRQ142, 174)
253 IRQ_HANDLER(IRQ143, 175)
254 IRQ_HANDLER(IRQ144, 176)
255 IRQ_HANDLER(IRQ145, 177)
256 IRQ_HANDLER(IRQ146, 178)
257 IRQ_HANDLER(IRQ147, 179)
258 IRQ_HANDLER(IRQ148, 180)
259 IRQ_HANDLER(IRQ149, 181)
260 IRQ_HANDLER(IRQ150, 182)
261 IRQ_HANDLER(IRQ151, 183)
262 IRQ_HANDLER(IRQ152, 184)
263 IRQ_HANDLER(IRQ153, 185)
264 IRQ_HANDLER(IRQ154, 186)
265 IRQ_HANDLER(IRQ155, 187)
266 IRQ_HANDLER(IRQ156, 188)
267 IRQ_HANDLER(IRQ157, 189)
268 IRQ_HANDLER(IRQ158, 190)
269 IRQ_HANDLER(IRQ159, 191)
270 IRQ_HANDLER(IRQ160, 192)
271 IRQ_HANDLER(IRQ161, 193)
272 IRQ_HANDLER(IRQ162, 194)
273 IRQ_HANDLER(IRQ163, 195)
274 IRQ_HANDLER(IRQ164, 196)
275 IRQ_HANDLER(IRQ165, 197)
276 IRQ_HANDLER(IRQ166, 198)
277 IRQ_HANDLER(IRQ167, 199)
278 IRQ_HANDLER(IRQ168, 200)
279 IRQ_HANDLER(IRQ169, 201)
280 IRQ_HANDLER(IRQ170, 202)
281 IRQ_HANDLER(IRQ171, 203)
282 IRQ_HANDLER(IRQ172, 204)
283 IRQ_HANDLER(IRQ173, 205)
284 IRQ_HANDLER(IRQ174, 206)
285 IRQ_HANDLER(IRQ175, 207)
286 IRQ_HANDLER(IRQ176, 208)
287 IRQ_HANDLER(IRQ177, 209)
288 IRQ_HANDLER(IRQ178, 210)
289 IRQ_HANDLER(IRQ179, 211)
290 IRQ_HANDLER(IRQ180, 212)
291 IRQ_HANDLER(IRQ181, 213)
292 IRQ_HANDLER(IRQ182, 214)
293 IRQ_HANDLER(IRQ183, 215)
294 IRQ_HANDLER(IRQ184, 216)
295 IRQ_HANDLER(IRQ185, 217)
296 IRQ_HANDLER(IRQ186, 218)
297 IRQ_HANDLER(IRQ187, 219)
298 IRQ_HANDLER(IRQ188, 220)
299 IRQ_HANDLER(IRQ189, 221)
300 IRQ_HANDLER(IRQ190, 222)
301 IRQ_HANDLER(IRQ191, 223)
302 IRQ_HANDLER(IRQ192, 224)
303 IRQ_HANDLER(IRQ193, 225)
304 IRQ_HANDLER(IRQ194, 226)
305 IRQ_HANDLER(IRQ195, 227)
306 IRQ_HANDLER(IRQ196, 228)
307 IRQ_HANDLER(IRQ197, 229)
308
309 /* 25 general purpose vectors, for use by the LAPIC.  Can expand later. */
310 IRQ_HANDLER(IRQ198, I_TESTING) # used in testing.c
311 IRQ_HANDLER(IRQ199, 231)
312 IRQ_HANDLER(IRQ200, 232)
313 IRQ_HANDLER(IRQ201, 233)
314 IRQ_HANDLER(IRQ202, 234)
315 IRQ_HANDLER(IRQ203, 235)
316 IRQ_HANDLER(IRQ204, 236)
317 IRQ_HANDLER(IRQ205, 237)
318 IRQ_HANDLER(IRQ206, 238)
319 IRQ_HANDLER(IRQ207, 239)
320 /* 0xf0 - start of the SMP_CALL IPIS */
321 IRQ_HANDLER(IRQ208, I_SMP_CALL0)
322 IRQ_HANDLER(IRQ209, I_SMP_CALL1)
323 IRQ_HANDLER(IRQ210, I_SMP_CALL2)
324 IRQ_HANDLER(IRQ211, I_SMP_CALL3)
325 IRQ_HANDLER(IRQ212, I_SMP_CALL4)
326 IRQ_HANDLER(IRQ213, 245)
327 IRQ_HANDLER(IRQ214, 246)
328 IRQ_HANDLER(IRQ215, 247)
329 IRQ_HANDLER(IRQ216, 248)
330 IRQ_HANDLER(IRQ217, 249)
331 IRQ_HANDLER(IRQ218, 250)
332 IRQ_HANDLER(IRQ219, 251)
333 IRQ_HANDLER(IRQ220, 252)
334 IRQ_HANDLER(IRQ221, 253)
335 POKE_HANDLER(IRQ222, 254)
336 IRQ_HANDLER(IRQ223, I_KERNEL_MSG)
337
338 /* Technically, these HANDLER entries do not need to be in numeric order */
339 TRAPHANDLER_NOEC(ISR_syscall, T_SYSCALL)
340 /* But make sure default is last!! */
341 TRAPHANDLER_NOEC(ISR_default, T_DEFAULT)
342
343 .data
344 .globl trap_tbl_end
345 trap_tbl_end:
346
347 .text
348 _alltraps:
349         cld
350         swapgs                  # harmless if we were already in the kernel
351         pushq %r15
352         pushq %r14
353         pushq %r13
354         pushq %r12
355         pushq %r11
356         pushq %r10
357         pushq %r9
358         pushq %r8
359         pushq %rdi
360         pushq %rsi
361         pushq %rbp
362         pushq %rdx
363         pushq %rcx
364         pushq %rbx
365         pushq %rax
366         cmpw $GD_KT, 0x90(%rsp) # 0x90 - diff btw tf_cs and tf_rax
367         je trap_kernel_tf
368         # this is a user TF, so we need to save their fs/gsbase and load gs base for
369         # the kernel.
370         movl $MSR_FS_BASE, %ecx
371         rdmsr
372         shl $32, %rdx
373         orq %rax, %rdx
374         pushq %rdx
375         # because we swapped gs earlier, the user GS is now in KERN_GS_BASE
376         movl $MSR_KERN_GS_BASE, %ecx
377         rdmsr
378         shl $32, %rdx
379         orq %rax, %rdx
380         pushq %rdx
381         # make sure the kernel's gs base is loaded into the KERN slot at all times
382         movl $MSR_GS_BASE, %ecx
383         rdmsr
384         movl $MSR_KERN_GS_BASE, %ecx
385         wrmsr
386         jmp trap_all_tf
387 trap_kernel_tf:
388         # we don't muck with fs/gsbase, push placeholders
389         movq $0xdeadbeef, %rax
390         pushq %rax
391         pushq %rax
392 trap_all_tf:
393         movq $0, %rbp                   # so we can backtrace to this point
394         movq %rsp, %rdi
395         call trap
396         # the return paths are only used by the kernel
397         addq $0x10, %rsp                        # skip fs/gs base
398         popq %rax
399         popq %rbx
400         popq %rcx
401         popq %rdx
402         popq %rbp
403         popq %rsi
404         popq %rdi
405         popq %r8
406         popq %r9
407         popq %r10
408         popq %r11
409         popq %r12
410         popq %r13
411         popq %r14
412         popq %r15
413         addq $0x10, %rsp                        # skip trapno and err
414         iretq
415
416 # might merge this with _alltraps
417 _allirqs:
418         cld
419         swapgs                  # harmless if we were already in the kernel
420         pushq %r15
421         pushq %r14
422         pushq %r13
423         pushq %r12
424         pushq %r11
425         pushq %r10
426         pushq %r9
427         pushq %r8
428         pushq %rdi
429         pushq %rsi
430         pushq %rbp
431         pushq %rdx
432         pushq %rcx
433         pushq %rbx
434         pushq %rax
435         cmpw $GD_KT, 0x90(%rsp) # 0x90 - diff btw tf_cs and tf_rax
436         je irq_kernel_tf
437         # this is a user TF, so we need to save their fs/gsbase and load gs base for
438         # the kernel.
439         movl $MSR_FS_BASE, %ecx
440         rdmsr
441         shl $32, %rdx
442         orq %rax, %rdx
443         pushq %rdx
444         # because we swapped gs earlier, the user GS is now in KERN_GS_BASE
445         movl $MSR_KERN_GS_BASE, %ecx
446         rdmsr
447         shl $32, %rdx
448         orq %rax, %rdx
449         pushq %rdx
450         # make sure the kernel's gs base is loaded into the KERN slot at all times
451         movl $MSR_GS_BASE, %ecx
452         rdmsr
453         movl $MSR_KERN_GS_BASE, %ecx
454         wrmsr
455         jmp irq_all_tf
456 irq_kernel_tf:
457         # we don't muck with fs/gsbase, push placeholders
458         movq $0xdeadbeef, %rax
459         pushq %rax
460         pushq %rax
461 irq_all_tf:
462         movq $0, %rbp                   # so we can backtrace to this point
463         movq %rsp, %rdi
464         call handle_irq
465         # the return paths are only used by the kernel
466         addq $0x10, %rsp                        # skip fs/gs base
467         popq %rax
468         popq %rbx
469         popq %rcx
470         popq %rdx
471         popq %rbp
472         popq %rsi
473         popq %rdi
474         popq %r8
475         popq %r9
476         popq %r10
477         popq %r11
478         popq %r12
479         popq %r13
480         popq %r14
481         popq %r15
482         addq $0x10, %rsp                        # skip trapno and err
483         iretq
484
485 .globl sysenter_handler;
486 .type sysenter_handler, @function;
487
488 sysenter_handler:
489 #ifndef CONFIG_NOFASTCALL_FSBASE
490         # Do a quick TLS / FS base change, never changing stacks.
491         # When rdi has the magic number, rsi has the new base
492         movabs $FASTCALL_SETFSBASE, %rax
493         cmp %rax, %rdi
494         jne normal_syscall      # could profile this and handle the jump differently
495         # need to check rsi, make sure it is canonical (will enfore below ULIM).
496         # need to either do this check, or handle the kernel GP fault on wrmsr.
497         movq %rsi, %rdi
498         shrq $47, %rdi
499         cmp $0, %rdi
500         jne fastcall_pop
501         # need to use cx, dx, and ax for the wrmsr.  dx and ax are free.
502         movq %rcx, %rdi         # save rcx, the retaddr
503         movq %rsi, %rdx
504         movq %rsi, %rax
505         shrq $32, %rdx
506         andl $0xffffffff, %eax
507         movl $MSR_FS_BASE, %ecx
508         wrmsr
509         movq %rdi, %rcx         # restore retaddr
510 fastcall_pop:
511         rex.w sysret
512 normal_syscall:
513 #endif
514         # cld is handled by the SFMASK
515         swapgs
516         movq %gs:0, %rsp
517         # Saving the FPU callee-saved state for now.  Might be able to have the
518         # preempt handler deal with it.
519         pushq $0                        # space for mxcsr and fpucw
520         fnstcw 0x4(%rsp)
521         stmxcsr (%rsp)
522         pushq %rdx                      # rsp, saved by userspace
523         pushq %rcx                      # rip, saved by hardware
524         pushq %r15
525         pushq %r14
526         pushq %r13
527         pushq %r12
528         pushq %rbp
529         pushq %rbx
530         # save fs and gs base
531         movl $MSR_FS_BASE, %ecx
532         rdmsr
533         shl $32, %rdx
534         orq %rax, %rdx
535         pushq %rdx
536         # because we swapped gs earlier, the user GS is now in KERN_GS_BASE
537         movl $MSR_KERN_GS_BASE, %ecx
538         rdmsr
539         shl $32, %rdx
540         orq %rax, %rdx
541         pushq %rdx
542         # make sure the kernel's gs base is loaded into the KERN slot at all times
543         movl $MSR_GS_BASE, %ecx
544         rdmsr
545         movl $MSR_KERN_GS_BASE, %ecx
546         wrmsr
547         movq $0, %rbp                   # so we can backtrace to this point
548         movq %rsp, %rdx
549         # arg0, rdi: struct sysc*.  arg1, rsi: count.  arg2, rdx: sw_tf
550         call sysenter_callwrapper
551         # return via pop_tf, never this path
552 sysenter_spin:
553         jmp sysenter_spin