Commit-ID:  46eabca284f9f27fe94698a068a4a21ba93b4975
Gitweb:     https://git.kernel.org/tip/46eabca284f9f27fe94698a068a4a21ba93b4975
Author:     Joerg Roedel <jroe...@suse.de>
AuthorDate: Wed, 18 Jul 2018 11:40:41 +0200
Committer:  Thomas Gleixner <t...@linutronix.de>
CommitDate: Fri, 20 Jul 2018 01:11:36 +0200

x86/entry/32: Put ESPFIX code into a macro

This makes it easier to split up the shared iret code path.

Signed-off-by: Joerg Roedel <jroe...@suse.de>
Signed-off-by: Thomas Gleixner <t...@linutronix.de>
Tested-by: Pavel Machek <pa...@ucw.cz>
Cc: "H . Peter Anvin" <h...@zytor.com>
Cc: linux...@kvack.org
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Andy Lutomirski <l...@kernel.org>
Cc: Dave Hansen <dave.han...@intel.com>
Cc: Josh Poimboeuf <jpoim...@redhat.com>
Cc: Juergen Gross <jgr...@suse.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Borislav Petkov <b...@alien8.de>
Cc: Jiri Kosina <jkos...@suse.cz>
Cc: Boris Ostrovsky <boris.ostrov...@oracle.com>
Cc: Brian Gerst <brge...@gmail.com>
Cc: David Laight <david.lai...@aculab.com>
Cc: Denys Vlasenko <dvlas...@redhat.com>
Cc: Eduardo Valentin <edu...@amazon.com>
Cc: Greg KH <gre...@linuxfoundation.org>
Cc: Will Deacon <will.dea...@arm.com>
Cc: aligu...@amazon.com
Cc: daniel.gr...@iaik.tugraz.at
Cc: hu...@google.com
Cc: keesc...@google.com
Cc: Andrea Arcangeli <aarca...@redhat.com>
Cc: Waiman Long <ll...@redhat.com>
Cc: "David H . Gutteridge" <dhgutteri...@sympatico.ca>
Cc: j...@8bytes.org
Link: 
https://lkml.kernel.org/r/1531906876-13451-5-git-send-email-j...@8bytes.org

---
 arch/x86/entry/entry_32.S | 97 ++++++++++++++++++++++++-----------------------
 1 file changed, 49 insertions(+), 48 deletions(-)

diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 39f711ad0fc9..ef7d65315e8e 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -221,6 +221,54 @@
        POP_GS_EX
 .endm
 
+.macro CHECK_AND_APPLY_ESPFIX
+#ifdef CONFIG_X86_ESPFIX32
+#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8)
+
+       ALTERNATIVE     "jmp .Lend_\@", "", X86_BUG_ESPFIX
+
+       movl    PT_EFLAGS(%esp), %eax           # mix EFLAGS, SS and CS
+       /*
+        * Warning: PT_OLDSS(%esp) contains the wrong/random values if we
+        * are returning to the kernel.
+        * See comments in process.c:copy_thread() for details.
+        */
+       movb    PT_OLDSS(%esp), %ah
+       movb    PT_CS(%esp), %al
+       andl    $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), 
%eax
+       cmpl    $((SEGMENT_LDT << 8) | USER_RPL), %eax
+       jne     .Lend_\@        # returning to user-space with LDT SS
+
+       /*
+        * Setup and switch to ESPFIX stack
+        *
+        * We're returning to userspace with a 16 bit stack. The CPU will not
+        * restore the high word of ESP for us on executing iret... This is an
+        * "official" bug of all the x86-compatible CPUs, which we can work
+        * around to make dosemu and wine happy. We do this by preloading the
+        * high word of ESP with the high word of the userspace ESP while
+        * compensating for the offset by changing to the ESPFIX segment with
+        * a base address that matches for the difference.
+        */
+       mov     %esp, %edx                      /* load kernel esp */
+       mov     PT_OLDESP(%esp), %eax           /* load userspace esp */
+       mov     %dx, %ax                        /* eax: new kernel esp */
+       sub     %eax, %edx                      /* offset (low word is 0) */
+       shr     $16, %edx
+       mov     %dl, GDT_ESPFIX_SS + 4          /* bits 16..23 */
+       mov     %dh, GDT_ESPFIX_SS + 7          /* bits 24..31 */
+       pushl   $__ESPFIX_SS
+       pushl   %eax                            /* new kernel esp */
+       /*
+        * Disable interrupts, but do not irqtrace this section: we
+        * will soon execute iret and the tracer was already set to
+        * the irqstate after the IRET:
+        */
+       DISABLE_INTERRUPTS(CLBR_ANY)
+       lss     (%esp), %esp                    /* switch to espfix segment */
+.Lend_\@:
+#endif /* CONFIG_X86_ESPFIX32 */
+.endm
 /*
  * %eax: prev task
  * %edx: next task
@@ -547,21 +595,7 @@ ENTRY(entry_INT80_32)
 restore_all:
        TRACE_IRQS_IRET
 .Lrestore_all_notrace:
-#ifdef CONFIG_X86_ESPFIX32
-       ALTERNATIVE     "jmp .Lrestore_nocheck", "", X86_BUG_ESPFIX
-
-       movl    PT_EFLAGS(%esp), %eax           # mix EFLAGS, SS and CS
-       /*
-        * Warning: PT_OLDSS(%esp) contains the wrong/random values if we
-        * are returning to the kernel.
-        * See comments in process.c:copy_thread() for details.
-        */
-       movb    PT_OLDSS(%esp), %ah
-       movb    PT_CS(%esp), %al
-       andl    $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), 
%eax
-       cmpl    $((SEGMENT_LDT << 8) | USER_RPL), %eax
-       je .Lldt_ss                             # returning to user-space with 
LDT SS
-#endif
+       CHECK_AND_APPLY_ESPFIX
 .Lrestore_nocheck:
        RESTORE_REGS 4                          # skip orig_eax/error_code
 .Lirq_return:
@@ -579,39 +613,6 @@ ENTRY(iret_exc     )
        jmp     common_exception
 .previous
        _ASM_EXTABLE(.Lirq_return, iret_exc)
-
-#ifdef CONFIG_X86_ESPFIX32
-.Lldt_ss:
-/*
- * Setup and switch to ESPFIX stack
- *
- * We're returning to userspace with a 16 bit stack. The CPU will not
- * restore the high word of ESP for us on executing iret... This is an
- * "official" bug of all the x86-compatible CPUs, which we can work
- * around to make dosemu and wine happy. We do this by preloading the
- * high word of ESP with the high word of the userspace ESP while
- * compensating for the offset by changing to the ESPFIX segment with
- * a base address that matches for the difference.
- */
-#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8)
-       mov     %esp, %edx                      /* load kernel esp */
-       mov     PT_OLDESP(%esp), %eax           /* load userspace esp */
-       mov     %dx, %ax                        /* eax: new kernel esp */
-       sub     %eax, %edx                      /* offset (low word is 0) */
-       shr     $16, %edx
-       mov     %dl, GDT_ESPFIX_SS + 4          /* bits 16..23 */
-       mov     %dh, GDT_ESPFIX_SS + 7          /* bits 24..31 */
-       pushl   $__ESPFIX_SS
-       pushl   %eax                            /* new kernel esp */
-       /*
-        * Disable interrupts, but do not irqtrace this section: we
-        * will soon execute iret and the tracer was already set to
-        * the irqstate after the IRET:
-        */
-       DISABLE_INTERRUPTS(CLBR_ANY)
-       lss     (%esp), %esp                    /* switch to espfix segment */
-       jmp     .Lrestore_nocheck
-#endif
 ENDPROC(entry_INT80_32)
 
 .macro FIXUP_ESPFIX_STACK

Reply via email to