[Midnightbsd-cvs] src [7895] trunk/sys/amd64/ia32: Real hardware, as opposed to QEMU, does not allow to have a call gate

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Sep 14 14:52:10 EDT 2016


Revision: 7895
          http://svnweb.midnightbsd.org/src/?rev=7895
Author:   laffer1
Date:     2016-09-14 14:52:10 -0400 (Wed, 14 Sep 2016)
Log Message:
-----------
Real hardware, as opposed to QEMU, does not allow to have a call gate
in long mode which transfers control to 32bit code segment. Unbreak
the lcall $7,$0 implementation on amd64 by putting the 64bit user code
segment' selector into call gate, and execute the 64bit trampoline
which converts the return frame into 32bit format and switches back to
32bit mode for executing int $0x80 trampoline.

Modified Paths:
--------------
    trunk/sys/amd64/ia32/ia32_sigtramp.S
    trunk/sys/amd64/ia32/ia32_syscall.c

Modified: trunk/sys/amd64/ia32/ia32_sigtramp.S
===================================================================
--- trunk/sys/amd64/ia32/ia32_sigtramp.S	2016-09-14 18:50:08 UTC (rev 7894)
+++ trunk/sys/amd64/ia32/ia32_sigtramp.S	2016-09-14 18:52:10 UTC (rev 7895)
@@ -91,8 +91,29 @@
  */
 	ALIGN_TEXT
 lcall_tramp:
+	.code64
+	/*
+	 * There, we are in 64bit mode and need to return to 32bit.
+	 * First, convert call frame from 64 to 32 bit format.
+	 */
+	pushq	%rax
+	movl	16(%rsp),%eax
+	movl	%eax,20(%rsp)	/* ret %cs */
+	movl	8(%rsp),%eax
+	movl	%eax,16(%rsp)	/* ret %rip -> %eip */
+	popq	%rax
+	addq	$8,%rsp
+	/* Now return to 32bit */
+	pushq	$0x33 /* _ucode32sel UPL */
+	callq	1f
+1:
+	addq	$2f-1b,(%rsp)
+	lretq
+2:
+	/* Back in 32bit mode */
+	.code32
 	cmpl	$SYS_vfork,%eax
-	je	2f
+	je	4f
 	pushl	%ebp
 	movl	%esp,%ebp
 	pushl	0x24(%ebp) /* arg 6 */
@@ -101,12 +122,12 @@
 	pushl	0x18(%ebp)
 	pushl	0x14(%ebp)
 	pushl	0x10(%ebp) /* arg 1 */
-	pushl	0xc(%ebp) /* gap */
+	pushl	0xc(%ebp)  /* gap */
 	int	$0x80
 	leavel
-1:
+3:
 	lretl
-2:
+4:
 	/*
 	 * vfork handling is special and relies on the libc stub saving
 	 * the return ip in %ecx.  If vfork failed, then there is no
@@ -113,7 +134,7 @@
 	 * child which can corrupt the frame created by call gate.
 	 */
 	int	$0x80
-	jb	1b
+	jb	3b
 	addl	$8,%esp
 	jmpl	*%ecx
 #endif

Modified: trunk/sys/amd64/ia32/ia32_syscall.c
===================================================================
--- trunk/sys/amd64/ia32/ia32_syscall.c	2016-09-14 18:50:08 UTC (rev 7894)
+++ trunk/sys/amd64/ia32/ia32_syscall.c	2016-09-14 18:52:10 UTC (rev 7895)
@@ -244,7 +244,7 @@
 	bzero(ssd, sizeof(*ssd));
 	ssd->gd_looffset = lcall_addr;
 	ssd->gd_hioffset = lcall_addr >> 16;
-	ssd->gd_selector = _ucode32sel;
+	ssd->gd_selector = _ucodesel;
 	ssd->gd_type = SDT_SYSCGT;
 	ssd->gd_dpl = SEL_UPL;
 	ssd->gd_p = 1;



More information about the Midnightbsd-cvs mailing list