Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1da177e4 | 2 | /* |
54ad726c IM |
3 | * Compatibility mode system call entry point for x86-64. |
4 | * | |
1da177e4 | 5 | * Copyright 2000-2002 Andi Kleen, SuSE Labs. |
54ad726c | 6 | */ |
d36f9479 | 7 | #include "calling.h" |
e2d5df93 | 8 | #include <asm/asm-offsets.h> |
1da177e4 LT |
9 | #include <asm/current.h> |
10 | #include <asm/errno.h> | |
54ad726c IM |
11 | #include <asm/ia32_unistd.h> |
12 | #include <asm/thread_info.h> | |
1da177e4 | 13 | #include <asm/segment.h> |
2601e64d | 14 | #include <asm/irqflags.h> |
1ce6f868 | 15 | #include <asm/asm.h> |
63bcff2a | 16 | #include <asm/smap.h> |
1da177e4 | 17 | #include <linux/linkage.h> |
d7e7528b | 18 | #include <linux/err.h> |
1da177e4 | 19 | |
ea714547 JO |
20 | .section .entry.text, "ax" |
21 | ||
1da177e4 | 22 | /* |
fda57b22 | 23 | * 32-bit SYSENTER entry. |
1da177e4 | 24 | * |
fda57b22 AL |
25 | * 32-bit system calls through the vDSO's __kernel_vsyscall enter here |
26 | * on 64-bit kernels running on Intel CPUs. | |
27 | * | |
28 | * The SYSENTER instruction, in principle, should *only* occur in the | |
29 | * vDSO. In practice, a small number of Android devices were shipped | |
30 | * with a copy of Bionic that inlined a SYSENTER instruction. This | |
31 | * never happened in any of Google's Bionic versions -- it only happened | |
32 | * in a narrow range of Intel-provided versions. | |
33 | * | |
34 | * SYSENTER loads SS, RSP, CS, and RIP from previously programmed MSRs. | |
35 | * IF and VM in RFLAGS are cleared (IOW: interrupts are off). | |
b87cf63e | 36 | * SYSENTER does not save anything on the stack, |
fda57b22 | 37 | * and does not save old RIP (!!!), RSP, or RFLAGS. |
b87cf63e | 38 | * |
1da177e4 | 39 | * Arguments: |
b87cf63e DV |
40 | * eax system call number |
41 | * ebx arg1 | |
42 | * ecx arg2 | |
43 | * edx arg3 | |
44 | * esi arg4 | |
45 | * edi arg5 | |
46 | * ebp user stack | |
47 | * 0(%ebp) arg6 | |
b87cf63e | 48 | */ |
4c8cd0c5 | 49 | ENTRY(entry_SYSENTER_compat) |
b611acf4 | 50 | /* Interrupts are off on entry. */ |
1a79797b | 51 | SWAPGS |
8a09317b DH |
52 | |
53 | /* We are about to clobber %rsp anyway, clobbering here is OK */ | |
54 | SWITCH_TO_KERNEL_CR3 scratch_reg=%rsp | |
55 | ||
3a23208e | 56 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp |
a232e3d5 | 57 | |
a474e67c AL |
58 | /* |
59 | * User tracing code (ptrace or signal handlers) might assume that | |
60 | * the saved RAX contains a 32-bit number when we're invoking a 32-bit | |
61 | * syscall. Just in case the high bits are nonzero, zero-extend | |
62 | * the syscall number. (This could almost certainly be deleted | |
63 | * with no ill effects.) | |
64 | */ | |
4ee8ec17 DV |
65 | movl %eax, %eax |
66 | ||
4c9c0e91 | 67 | /* Construct struct pt_regs on stack */ |
131484c8 | 68 | pushq $__USER32_DS /* pt_regs->ss */ |
30bfa7b3 | 69 | pushq %rbp /* pt_regs->sp (stashed in bp) */ |
b611acf4 AL |
70 | |
71 | /* | |
72 | * Push flags. This is nasty. First, interrupts are currently | |
73 | * off, but we need pt_regs->flags to have IF set. Second, even | |
74 | * if TF was set when SYSENTER started, it's clear by now. We fix | |
75 | * that later using TIF_SINGLESTEP. | |
76 | */ | |
77 | pushfq /* pt_regs->flags (except IF = 0) */ | |
78 | orl $X86_EFLAGS_IF, (%rsp) /* Fix saved flags */ | |
131484c8 | 79 | pushq $__USER32_CS /* pt_regs->cs */ |
778843f9 | 80 | pushq $0 /* pt_regs->ip = 0 (placeholder) */ |
131484c8 IM |
81 | pushq %rax /* pt_regs->orig_ax */ |
82 | pushq %rdi /* pt_regs->di */ | |
83 | pushq %rsi /* pt_regs->si */ | |
84 | pushq %rdx /* pt_regs->dx */ | |
30bfa7b3 | 85 | pushq %rcx /* pt_regs->cx */ |
131484c8 | 86 | pushq $-ENOSYS /* pt_regs->ax */ |
778843f9 | 87 | pushq $0 /* pt_regs->r8 = 0 */ |
ced5d0bf | 88 | xorl %r8d, %r8d /* nospec r8 */ |
778843f9 | 89 | pushq $0 /* pt_regs->r9 = 0 */ |
ced5d0bf | 90 | xorl %r9d, %r9d /* nospec r9 */ |
778843f9 | 91 | pushq $0 /* pt_regs->r10 = 0 */ |
ced5d0bf | 92 | xorl %r10d, %r10d /* nospec r10 */ |
778843f9 | 93 | pushq $0 /* pt_regs->r11 = 0 */ |
ced5d0bf | 94 | xorl %r11d, %r11d /* nospec r11 */ |
a474e67c | 95 | pushq %rbx /* pt_regs->rbx */ |
6b8cf5cc | 96 | xorl %ebx, %ebx /* nospec rbx */ |
30bfa7b3 | 97 | pushq %rbp /* pt_regs->rbp (will be overwritten) */ |
6b8cf5cc | 98 | xorl %ebp, %ebp /* nospec rbp */ |
778843f9 | 99 | pushq $0 /* pt_regs->r12 = 0 */ |
ced5d0bf | 100 | xorl %r12d, %r12d /* nospec r12 */ |
778843f9 | 101 | pushq $0 /* pt_regs->r13 = 0 */ |
ced5d0bf | 102 | xorl %r13d, %r13d /* nospec r13 */ |
778843f9 | 103 | pushq $0 /* pt_regs->r14 = 0 */ |
ced5d0bf | 104 | xorl %r14d, %r14d /* nospec r14 */ |
778843f9 | 105 | pushq $0 /* pt_regs->r15 = 0 */ |
ced5d0bf | 106 | xorl %r15d, %r15d /* nospec r15 */ |
1da177e4 | 107 | cld |
4c9c0e91 | 108 | |
8c7aa698 | 109 | /* |
e7860411 | 110 | * SYSENTER doesn't filter flags, so we need to clear NT and AC |
8c7aa698 | 111 | * ourselves. To save a few cycles, we can check whether |
e7860411 | 112 | * either was set instead of doing an unconditional popfq. |
b611acf4 AL |
113 | * This needs to happen before enabling interrupts so that |
114 | * we don't get preempted with NT set. | |
374a3a39 | 115 | * |
f2b37575 AL |
116 | * If TF is set, we will single-step all the way to here -- do_debug |
117 | * will ignore all the traps. (Yes, this is slow, but so is | |
118 | * single-stepping in general. This allows us to avoid having | |
119 | * a more complicated code to handle the case where a user program | |
120 | * forces us to single-step through the SYSENTER entry code.) | |
121 | * | |
f74acf0e | 122 | * NB.: .Lsysenter_fix_flags is a label with the code under it moved |
374a3a39 BP |
123 | * out-of-line as an optimization: NT is unlikely to be set in the |
124 | * majority of the cases and instead of polluting the I$ unnecessarily, | |
125 | * we're keeping that code behind a branch which will predict as | |
126 | * not-taken and therefore its instructions won't be fetched. | |
8c7aa698 | 127 | */ |
f2b37575 | 128 | testl $X86_EFLAGS_NT|X86_EFLAGS_AC|X86_EFLAGS_TF, EFLAGS(%rsp) |
f74acf0e BP |
129 | jnz .Lsysenter_fix_flags |
130 | .Lsysenter_flags_fixed: | |
8c7aa698 | 131 | |
a474e67c AL |
132 | /* |
133 | * User mode is traced as though IRQs are on, and SYSENTER | |
134 | * turned them off. | |
135 | */ | |
136 | TRACE_IRQS_OFF | |
e62a254a | 137 | |
a474e67c AL |
138 | movq %rsp, %rdi |
139 | call do_fast_syscall_32 | |
91e2eea9 BO |
140 | /* XEN PV guests always use IRET path */ |
141 | ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \ | |
142 | "jmp .Lsyscall_32_done", X86_FEATURE_XENPV | |
7841b408 | 143 | jmp sysret32_from_system_call |
1da177e4 | 144 | |
f74acf0e | 145 | .Lsysenter_fix_flags: |
b611acf4 | 146 | pushq $X86_EFLAGS_FIXED |
131484c8 | 147 | popfq |
f74acf0e | 148 | jmp .Lsysenter_flags_fixed |
f2b37575 | 149 | GLOBAL(__end_entry_SYSENTER_compat) |
4c8cd0c5 | 150 | ENDPROC(entry_SYSENTER_compat) |
1da177e4 LT |
151 | |
152 | /* | |
fda57b22 AL |
153 | * 32-bit SYSCALL entry. |
154 | * | |
155 | * 32-bit system calls through the vDSO's __kernel_vsyscall enter here | |
156 | * on 64-bit kernels running on AMD CPUs. | |
157 | * | |
158 | * The SYSCALL instruction, in principle, should *only* occur in the | |
159 | * vDSO. In practice, it appears that this really is the case. | |
160 | * As evidence: | |
161 | * | |
162 | * - The calling convention for SYSCALL has changed several times without | |
163 | * anyone noticing. | |
164 | * | |
165 | * - Prior to the in-kernel X86_BUG_SYSRET_SS_ATTRS fixup, anything | |
166 | * user task that did SYSCALL without immediately reloading SS | |
167 | * would randomly crash. | |
1da177e4 | 168 | * |
fda57b22 AL |
169 | * - Most programmers do not directly target AMD CPUs, and the 32-bit |
170 | * SYSCALL instruction does not exist on Intel CPUs. Even on AMD | |
171 | * CPUs, Linux disables the SYSCALL instruction on 32-bit kernels | |
172 | * because the SYSCALL instruction in legacy/native 32-bit mode (as | |
173 | * opposed to compat mode) is sufficiently poorly designed as to be | |
174 | * essentially unusable. | |
b87cf63e | 175 | * |
fda57b22 AL |
176 | * 32-bit SYSCALL saves RIP to RCX, clears RFLAGS.RF, then saves |
177 | * RFLAGS to R11, then loads new SS, CS, and RIP from previously | |
178 | * programmed MSRs. RFLAGS gets masked by a value from another MSR | |
179 | * (so CLD and CLAC are not needed). SYSCALL does not save anything on | |
180 | * the stack and does not change RSP. | |
181 | * | |
182 | * Note: RFLAGS saving+masking-with-MSR happens only in Long mode | |
54ad726c | 183 | * (in legacy 32-bit mode, IF, RF and VM bits are cleared and that's it). |
fda57b22 | 184 | * Don't get confused: RFLAGS saving+masking depends on Long Mode Active bit |
b87cf63e DV |
185 | * (EFER.LMA=1), NOT on bitness of userspace where SYSCALL executes |
186 | * or target CS descriptor's L bit (SYSCALL does not read segment descriptors). | |
187 | * | |
1da177e4 | 188 | * Arguments: |
b87cf63e DV |
189 | * eax system call number |
190 | * ecx return address | |
191 | * ebx arg1 | |
192 | * ebp arg2 (note: not saved in the stack frame, should not be touched) | |
193 | * edx arg3 | |
194 | * esi arg4 | |
195 | * edi arg5 | |
196 | * esp user stack | |
197 | * 0(%esp) arg6 | |
b87cf63e | 198 | */ |
2cd23553 | 199 | ENTRY(entry_SYSCALL_compat) |
a474e67c | 200 | /* Interrupts are off on entry. */ |
8a9949bc | 201 | swapgs |
e62a254a | 202 | |
d7732ba5 | 203 | /* Stash user ESP */ |
54ad726c | 204 | movl %esp, %r8d |
d7732ba5 TG |
205 | |
206 | /* Use %rsp as scratch reg. User ESP is stashed in r8 */ | |
207 | SWITCH_TO_KERNEL_CR3 scratch_reg=%rsp | |
208 | ||
209 | /* Switch to the kernel stack */ | |
54ad726c | 210 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp |
a232e3d5 | 211 | |
4c9c0e91 | 212 | /* Construct struct pt_regs on stack */ |
131484c8 IM |
213 | pushq $__USER32_DS /* pt_regs->ss */ |
214 | pushq %r8 /* pt_regs->sp */ | |
215 | pushq %r11 /* pt_regs->flags */ | |
216 | pushq $__USER32_CS /* pt_regs->cs */ | |
217 | pushq %rcx /* pt_regs->ip */ | |
8a9949bc AL |
218 | GLOBAL(entry_SYSCALL_compat_after_hwframe) |
219 | movl %eax, %eax /* discard orig_ax high bits */ | |
131484c8 IM |
220 | pushq %rax /* pt_regs->orig_ax */ |
221 | pushq %rdi /* pt_regs->di */ | |
222 | pushq %rsi /* pt_regs->si */ | |
223 | pushq %rdx /* pt_regs->dx */ | |
30bfa7b3 | 224 | pushq %rbp /* pt_regs->cx (stashed in bp) */ |
131484c8 | 225 | pushq $-ENOSYS /* pt_regs->ax */ |
778843f9 | 226 | pushq $0 /* pt_regs->r8 = 0 */ |
ced5d0bf | 227 | xorl %r8d, %r8d /* nospec r8 */ |
778843f9 | 228 | pushq $0 /* pt_regs->r9 = 0 */ |
ced5d0bf | 229 | xorl %r9d, %r9d /* nospec r9 */ |
778843f9 | 230 | pushq $0 /* pt_regs->r10 = 0 */ |
ced5d0bf | 231 | xorl %r10d, %r10d /* nospec r10 */ |
778843f9 | 232 | pushq $0 /* pt_regs->r11 = 0 */ |
ced5d0bf | 233 | xorl %r11d, %r11d /* nospec r11 */ |
a474e67c | 234 | pushq %rbx /* pt_regs->rbx */ |
6b8cf5cc | 235 | xorl %ebx, %ebx /* nospec rbx */ |
30bfa7b3 | 236 | pushq %rbp /* pt_regs->rbp (will be overwritten) */ |
6b8cf5cc | 237 | xorl %ebp, %ebp /* nospec rbp */ |
778843f9 | 238 | pushq $0 /* pt_regs->r12 = 0 */ |
ced5d0bf | 239 | xorl %r12d, %r12d /* nospec r12 */ |
778843f9 | 240 | pushq $0 /* pt_regs->r13 = 0 */ |
ced5d0bf | 241 | xorl %r13d, %r13d /* nospec r13 */ |
778843f9 | 242 | pushq $0 /* pt_regs->r14 = 0 */ |
ced5d0bf | 243 | xorl %r14d, %r14d /* nospec r14 */ |
778843f9 | 244 | pushq $0 /* pt_regs->r15 = 0 */ |
ced5d0bf | 245 | xorl %r15d, %r15d /* nospec r15 */ |
4c9c0e91 | 246 | |
a474e67c AL |
247 | /* |
248 | * User mode is traced as though IRQs are on, and SYSENTER | |
249 | * turned them off. | |
250 | */ | |
251 | TRACE_IRQS_OFF | |
252 | ||
253 | movq %rsp, %rdi | |
254 | call do_fast_syscall_32 | |
91e2eea9 BO |
255 | /* XEN PV guests always use IRET path */ |
256 | ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \ | |
257 | "jmp .Lsyscall_32_done", X86_FEATURE_XENPV | |
7841b408 AL |
258 | |
259 | /* Opportunistic SYSRET */ | |
260 | sysret32_from_system_call: | |
261 | TRACE_IRQS_ON /* User mode traces as IRQs on. */ | |
262 | movq RBX(%rsp), %rbx /* pt_regs->rbx */ | |
263 | movq RBP(%rsp), %rbp /* pt_regs->rbp */ | |
264 | movq EFLAGS(%rsp), %r11 /* pt_regs->flags (in r11) */ | |
265 | movq RIP(%rsp), %rcx /* pt_regs->ip (in rcx) */ | |
266 | addq $RAX, %rsp /* Skip r8-r15 */ | |
267 | popq %rax /* pt_regs->rax */ | |
268 | popq %rdx /* Skip pt_regs->cx */ | |
269 | popq %rdx /* pt_regs->dx */ | |
270 | popq %rsi /* pt_regs->si */ | |
271 | popq %rdi /* pt_regs->di */ | |
272 | ||
273 | /* | |
274 | * USERGS_SYSRET32 does: | |
275 | * GSBASE = user's GS base | |
276 | * EIP = ECX | |
277 | * RFLAGS = R11 | |
278 | * CS = __USER32_CS | |
279 | * SS = __USER_DS | |
280 | * | |
281 | * ECX will not match pt_regs->cx, but we're returning to a vDSO | |
282 | * trampoline that will fix up RCX, so this is okay. | |
283 | * | |
284 | * R12-R15 are callee-saved, so they contain whatever was in them | |
285 | * when the system call started, which is already known to user | |
286 | * code. We zero R8-R10 to avoid info leaks. | |
287 | */ | |
8a09317b DH |
288 | movq RSP-ORIG_RAX(%rsp), %rsp |
289 | ||
290 | /* | |
291 | * The original userspace %rsp (RSP-ORIG_RAX(%rsp)) is stored | |
292 | * on the process stack which is not mapped to userspace and | |
293 | * not readable after we SWITCH_TO_USER_CR3. Delay the CR3 | |
294 | * switch until after after the last reference to the process | |
295 | * stack. | |
296 | * | |
6fd166aa | 297 | * %r8/%r9 are zeroed before the sysret, thus safe to clobber. |
8a09317b | 298 | */ |
6fd166aa | 299 | SWITCH_TO_USER_CR3_NOSTACK scratch_reg=%r8 scratch_reg2=%r9 |
8a09317b | 300 | |
ced5d0bf DB |
301 | xorl %r8d, %r8d |
302 | xorl %r9d, %r9d | |
303 | xorl %r10d, %r10d | |
75ef8219 BO |
304 | swapgs |
305 | sysretl | |
2cd23553 | 306 | END(entry_SYSCALL_compat) |
54ad726c | 307 | |
b87cf63e | 308 | /* |
fda57b22 AL |
309 | * 32-bit legacy system call entry. |
310 | * | |
311 | * 32-bit x86 Linux system calls traditionally used the INT $0x80 | |
312 | * instruction. INT $0x80 lands here. | |
313 | * | |
314 | * This entry point can be used by 32-bit and 64-bit programs to perform | |
315 | * 32-bit system calls. Instances of INT $0x80 can be found inline in | |
316 | * various programs and libraries. It is also used by the vDSO's | |
317 | * __kernel_vsyscall fallback for hardware that doesn't support a faster | |
318 | * entry method. Restarted 32-bit system calls also fall back to INT | |
319 | * $0x80 regardless of what instruction was originally used to do the | |
320 | * system call. | |
321 | * | |
322 | * This is considered a slow path. It is not used by most libc | |
323 | * implementations on modern hardware except during process startup. | |
1da177e4 | 324 | * |
b87cf63e DV |
325 | * Arguments: |
326 | * eax system call number | |
327 | * ebx arg1 | |
328 | * ecx arg2 | |
329 | * edx arg3 | |
330 | * esi arg4 | |
331 | * edi arg5 | |
fda57b22 | 332 | * ebp arg6 |
b87cf63e | 333 | */ |
2cd23553 | 334 | ENTRY(entry_INT80_compat) |
2601e64d | 335 | /* |
a232e3d5 | 336 | * Interrupts are off on entry. |
2601e64d | 337 | */ |
3d44d51b | 338 | ASM_CLAC /* Do this early to minimize exposure */ |
a232e3d5 | 339 | SWAPGS |
a232e3d5 | 340 | |
ee08c6bd AL |
341 | /* |
342 | * User tracing code (ptrace or signal handlers) might assume that | |
343 | * the saved RAX contains a 32-bit number when we're invoking a 32-bit | |
344 | * syscall. Just in case the high bits are nonzero, zero-extend | |
345 | * the syscall number. (This could almost certainly be deleted | |
346 | * with no ill effects.) | |
347 | */ | |
54ad726c | 348 | movl %eax, %eax |
4ee8ec17 | 349 | |
f3d415ea | 350 | /* switch to thread stack expects orig_ax and rdi to be pushed */ |
131484c8 | 351 | pushq %rax /* pt_regs->orig_ax */ |
f3d415ea DB |
352 | pushq %rdi /* pt_regs->di */ |
353 | ||
354 | /* Need to switch before accessing the thread stack. */ | |
355 | SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi | |
356 | movq %rsp, %rdi | |
357 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp | |
358 | ||
359 | pushq 6*8(%rdi) /* regs->ss */ | |
360 | pushq 5*8(%rdi) /* regs->rsp */ | |
361 | pushq 4*8(%rdi) /* regs->eflags */ | |
362 | pushq 3*8(%rdi) /* regs->cs */ | |
363 | pushq 2*8(%rdi) /* regs->ip */ | |
364 | pushq 1*8(%rdi) /* regs->orig_ax */ | |
7f2590a1 | 365 | |
91c5f0de | 366 | pushq (%rdi) /* pt_regs->di */ |
131484c8 IM |
367 | pushq %rsi /* pt_regs->si */ |
368 | pushq %rdx /* pt_regs->dx */ | |
369 | pushq %rcx /* pt_regs->cx */ | |
370 | pushq $-ENOSYS /* pt_regs->ax */ | |
778843f9 | 371 | pushq $0 /* pt_regs->r8 = 0 */ |
ced5d0bf | 372 | xorl %r8d, %r8d /* nospec r8 */ |
778843f9 | 373 | pushq $0 /* pt_regs->r9 = 0 */ |
ced5d0bf | 374 | xorl %r9d, %r9d /* nospec r9 */ |
778843f9 | 375 | pushq $0 /* pt_regs->r10 = 0 */ |
ced5d0bf | 376 | xorl %r10d, %r10d /* nospec r10 */ |
778843f9 | 377 | pushq $0 /* pt_regs->r11 = 0 */ |
ced5d0bf | 378 | xorl %r11d, %r11d /* nospec r11 */ |
8169aff6 | 379 | pushq %rbx /* pt_regs->rbx */ |
6b8cf5cc | 380 | xorl %ebx, %ebx /* nospec rbx */ |
8169aff6 | 381 | pushq %rbp /* pt_regs->rbp */ |
6b8cf5cc | 382 | xorl %ebp, %ebp /* nospec rbp */ |
8169aff6 | 383 | pushq %r12 /* pt_regs->r12 */ |
ced5d0bf | 384 | xorl %r12d, %r12d /* nospec r12 */ |
8169aff6 | 385 | pushq %r13 /* pt_regs->r13 */ |
ced5d0bf | 386 | xorl %r13d, %r13d /* nospec r13 */ |
8169aff6 | 387 | pushq %r14 /* pt_regs->r14 */ |
ced5d0bf | 388 | xorl %r14d, %r14d /* nospec r14 */ |
8169aff6 | 389 | pushq %r15 /* pt_regs->r15 */ |
ced5d0bf | 390 | xorl %r15d, %r15d /* nospec r15 */ |
1da177e4 | 391 | cld |
54ad726c | 392 | |
73cbf687 | 393 | /* |
ee08c6bd AL |
394 | * User mode is traced as though IRQs are on, and the interrupt |
395 | * gate turned them off. | |
73cbf687 | 396 | */ |
ee08c6bd AL |
397 | TRACE_IRQS_OFF |
398 | ||
399 | movq %rsp, %rdi | |
a798f091 | 400 | call do_int80_syscall_32 |
a474e67c | 401 | .Lsyscall_32_done: |
ee08c6bd AL |
402 | |
403 | /* Go back to user mode. */ | |
404 | TRACE_IRQS_ON | |
8a055d7f | 405 | jmp swapgs_restore_regs_and_return_to_usermode |
2cd23553 | 406 | END(entry_INT80_compat) |