diff options
Diffstat (limited to 'arch/x86/kernel/entry_64.S')
-rw-r--r-- | arch/x86/kernel/entry_64.S | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index ddee7b2abe25..f5fdc8112116 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1445,12 +1445,17 @@ ENTRY(error_entry) */ SWITCH_KERNEL_CR3 testl $3,CS+8(%rsp) - je error_kernelspace + jz .Lerror_kernelspace - /* We entered from user mode */ +.Lerror_entry_from_usermode_swapgs: + /* + * We entered from user mode or we're pretending to have entered + * from user mode due to an IRET fault. + */ SWAPGS -error_entry_done: +.Lerror_entry_from_usermode_after_swapgs: +.Lerror_entry_done: TRACE_IRQS_OFF ret @@ -1460,30 +1465,29 @@ error_entry_done: * truncated RIP for IRET exceptions returning to compat mode. Check * for these here too. */ -error_kernelspace: +.Lerror_kernelspace: leaq native_irq_return_iret(%rip),%rcx cmpq %rcx,RIP+8(%rsp) - je error_bad_iret + je .Lerror_bad_iret movl %ecx,%eax /* zero extend */ cmpq %rax,RIP+8(%rsp) - je bstep_iret + je .Lbstep_iret cmpq $gs_change,RIP+8(%rsp) - jne error_entry_done + jne .Lerror_entry_done /* * hack: gs_change can fail with user gsbase. If this happens, fix up * gsbase and proceed. We'll fix up the exception and land in * gs_change's error handler with kernel gsbase. */ - SWAPGS - jmp error_entry_done + jmp .Lerror_entry_from_usermode_swapgs -bstep_iret: +.Lbstep_iret: /* Fix truncated RIP */ movq %rcx,RIP+8(%rsp) /* fall through */ -error_bad_iret: +.Lerror_bad_iret: /* * We came from an IRET to user mode, so we have user gsbase. * Switch to kernel gsbase: @@ -1497,7 +1501,7 @@ error_bad_iret: mov %rsp,%rdi call fixup_bad_iret mov %rax,%rsp - jmp error_entry_done + jmp .Lerror_entry_from_usermode_after_swapgs CFI_ENDPROC END(error_entry) |