Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1285988 > unrolled thread

[PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

Started byAndy Lutomirski <luto@kernel.org>
First post2015-12-07 23:00 +0100
Last post2015-12-09 20:40 +0100
Articles 19 — 4 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path Andy Lutomirski <luto@kernel.org> - 2015-12-07 23:00 +0100
    Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Brian Gerst <brgerst@gmail.com> - 2015-12-08 02:00 +0100
      Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Andy Lutomirski <luto@amacapital.net> - 2015-12-08 02:20 +0100
        Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Brian Gerst <brgerst@gmail.com> - 2015-12-08 14:10 +0100
          Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Ingo Molnar <mingo@kernel.org> - 2015-12-08 20:00 +0100
            Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Andy Lutomirski <luto@amacapital.net> - 2015-12-08 23:00 +0100
    Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Brian Gerst <brgerst@gmail.com> - 2015-12-08 02:00 +0100
    Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Brian Gerst <brgerst@gmail.com> - 2015-12-09 05:50 +0100
      Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Andy Lutomirski <luto@amacapital.net> - 2015-12-09 06:50 +0100
        Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Andy Lutomirski <luto@amacapital.net> - 2015-12-09 07:30 +0100
          Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on  the slow path Brian Gerst <brgerst@gmail.com> - 2015-12-09 14:00 +0100
          [PATCH] x86/entry/64: Remove duplicate syscall table for fast path Brian Gerst <brgerst@gmail.com> - 2015-12-09 14:10 +0100
            Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path Andy Lutomirski <luto@amacapital.net> - 2015-12-09 20:00 +0100
              Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path Brian Gerst <brgerst@gmail.com> - 2015-12-09 22:10 +0100
                Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path Andy Lutomirski <luto@amacapital.net> - 2015-12-09 22:20 +0100
                  Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path Andy Lutomirski <luto@amacapital.net> - 2015-12-10 01:00 +0100
                    Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path Brian Gerst <brgerst@gmail.com> - 2015-12-10 06:50 +0100
                      Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path Andy Lutomirski <luto@amacapital.net> - 2015-12-10 07:00 +0100
            [PATCH] x86/entry/64: Remove duplicate syscall table for fast path Andy Lutomirski <luto@kernel.org> - 2015-12-09 20:40 +0100

#1285988 — [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromAndy Lutomirski <luto@kernel.org>
Date2015-12-07 23:00 +0100
Subject[PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDbZ9-1Mo-37@gated-at.bofh.it>
64-bit syscalls currently have an optimization in which they are
called with partial pt_regs.  A small handful require full pt_regs.

In the 32-bit and compat cases, I cleaned this up by forcing full
pt_regs for all syscalls.  The performance hit doesn't really matter.

I want to clean up the 64-bit case as well, but I don't want to hurt
fast path performance.  To do that, I want to force the syscalls
that use pt_regs onto the slow path.  This will enable us to make
slow path syscalls be real ABI-compliant C functions.

Use the new syscall entry qualification machinery for this.
stub_clone is now stub_clone/ptregs.

The next patch will eliminate the stubs, and we'll just have
sys_clone/ptregs.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/entry/entry_64.S              | 17 +++++++++--------
 arch/x86/entry/syscall_64.c            | 18 ++++++++++++++++++
 arch/x86/entry/syscalls/syscall_64.tbl | 16 ++++++++--------
 3 files changed, 35 insertions(+), 16 deletions(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 9d34d3cfceb6..a698b8092831 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -182,7 +182,7 @@ entry_SYSCALL_64_fastpath:
 #endif
 	ja	1f				/* return -ENOSYS (already in pt_regs->ax) */
 	movq	%r10, %rcx
-	call	*sys_call_table(, %rax, 8)
+	call	*sys_call_table_fastpath_64(, %rax, 8)
 	movq	%rax, RAX(%rsp)
 1:
 /*
@@ -238,13 +238,6 @@ tracesys:
 	movq	%rsp, %rdi
 	movl	$AUDIT_ARCH_X86_64, %esi
 	call	syscall_trace_enter_phase1
-	test	%rax, %rax
-	jnz	tracesys_phase2			/* if needed, run the slow path */
-	RESTORE_C_REGS_EXCEPT_RAX		/* else restore clobbered regs */
-	movq	ORIG_RAX(%rsp), %rax
-	jmp	entry_SYSCALL_64_fastpath	/* and return to the fast path */
-
-tracesys_phase2:
 	SAVE_EXTRA_REGS
 	movq	%rsp, %rdi
 	movl	$AUDIT_ARCH_X86_64, %esi
@@ -355,6 +348,14 @@ opportunistic_sysret_failed:
 	jmp	restore_c_regs_and_iret
 END(entry_SYSCALL_64)
 
+ENTRY(stub_ptregs_64)
+	/*
+	 * Syscalls marked as needing ptregs that go through the fast path
+	 * land here.  We transfer to the slow path.
+	 */
+	addq	$8, %rsp
+	jmp	tracesys
+END(stub_ptregs_64)
 
 	.macro FORK_LIKE func
 ENTRY(stub_\func)
diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
index a1d408772ae6..601745c667ce 100644
--- a/arch/x86/entry/syscall_64.c
+++ b/arch/x86/entry/syscall_64.c
@@ -22,3 +22,21 @@ asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
 	[0 ... __NR_syscall_max] = &sys_ni_syscall,
 #include <asm/syscalls_64.h>
 };
+
+#undef __SYSCALL_64
+
+extern long stub_ptregs_64(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
+
+#define __SYSCALL_64_QUAL_(nr, sym) [nr] = sym,
+#define __SYSCALL_64_QUAL_ptregs(nr, sym) [nr] = stub_ptregs_64,
+
+#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(nr, sym)
+
+asmlinkage const sys_call_ptr_t sys_call_table_fastpath_64[__NR_syscall_max+1] = {
+	/*
+	 * Smells like a compiler bug -- it doesn't work
+	 * when the & below is removed.
+	 */
+	[0 ... __NR_syscall_max] = &sys_ni_syscall,
+#include <asm/syscalls_64.h>
+};
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 278842fdf1f6..6b9db2e338f4 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -21,7 +21,7 @@
 12	common	brk			sys_brk
 13	64	rt_sigaction		sys_rt_sigaction
 14	common	rt_sigprocmask		sys_rt_sigprocmask
-15	64	rt_sigreturn		stub_rt_sigreturn
+15	64	rt_sigreturn		stub_rt_sigreturn/ptregs
 16	64	ioctl			sys_ioctl
 17	common	pread64			sys_pread64
 18	common	pwrite64		sys_pwrite64
@@ -62,10 +62,10 @@
 53	common	socketpair		sys_socketpair
 54	64	setsockopt		sys_setsockopt
 55	64	getsockopt		sys_getsockopt
-56	common	clone			stub_clone
-57	common	fork			stub_fork
-58	common	vfork			stub_vfork
-59	64	execve			stub_execve
+56	common	clone			stub_clone/ptregs
+57	common	fork			stub_fork/ptregs
+58	common	vfork			stub_vfork/ptregs
+59	64	execve			stub_execve/ptregs
 60	common	exit			sys_exit
 61	common	wait4			sys_wait4
 62	common	kill			sys_kill
@@ -328,7 +328,7 @@
 319	common	memfd_create		sys_memfd_create
 320	common	kexec_file_load		sys_kexec_file_load
 321	common	bpf			sys_bpf
-322	64	execveat		stub_execveat
+322	64	execveat		stub_execveat/ptregs
 323	common	userfaultfd		sys_userfaultfd
 324	common	membarrier		sys_membarrier
 
@@ -344,7 +344,7 @@
 517	x32	recvfrom		compat_sys_recvfrom
 518	x32	sendmsg			compat_sys_sendmsg
 519	x32	recvmsg			compat_sys_recvmsg
-520	x32	execve			stub_x32_execve
+520	x32	execve			stub_x32_execve/ptregs
 521	x32	ptrace			compat_sys_ptrace
 522	x32	rt_sigpending		compat_sys_rt_sigpending
 523	x32	rt_sigtimedwait		compat_sys_rt_sigtimedwait
@@ -369,4 +369,4 @@
 542	x32	getsockopt		compat_sys_getsockopt
 543	x32	io_setup		compat_sys_io_setup
 544	x32	io_submit		compat_sys_io_submit
-545	x32	execveat		stub_x32_execveat
+545	x32	execveat		stub_x32_execveat/ptregs
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1286132 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromBrian Gerst <brgerst@gmail.com>
Date2015-12-08 02:00 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDeNj-3D4-1@gated-at.bofh.it>
In reply to#1285988
On Mon, Dec 7, 2015 at 7:50 PM, Brian Gerst <brgerst@gmail.com> wrote:
> On Mon, Dec 7, 2015 at 4:51 PM, Andy Lutomirski <luto@kernel.org> wrote:
>> 64-bit syscalls currently have an optimization in which they are
>> called with partial pt_regs.  A small handful require full pt_regs.
>>
>> In the 32-bit and compat cases, I cleaned this up by forcing full
>> pt_regs for all syscalls.  The performance hit doesn't really matter.
>>
>> I want to clean up the 64-bit case as well, but I don't want to hurt
>> fast path performance.  To do that, I want to force the syscalls
>> that use pt_regs onto the slow path.  This will enable us to make
>> slow path syscalls be real ABI-compliant C functions.
>>
>> Use the new syscall entry qualification machinery for this.
>> stub_clone is now stub_clone/ptregs.
>>
>> The next patch will eliminate the stubs, and we'll just have
>> sys_clone/ptregs.

[Resend after gmail web interface fail]

I've got an idea on how to do this without the duplicate syscall table.

ptregs_foo:
    leaq sys_foo(%rip), %rax
    jmp stub_ptregs_64

stub_ptregs_64:
    testl $TS_EXTRAREGS, <current->ti_status>
    jnz 1f
    SAVE_EXTRA_REGS
    call *%rax
    RESTORE_EXTRA_REGS
    ret
1:
    call *%rax
    ret

This makes sure that the extra regs don't get saved a second time if
coming in from the slow path, but preserves the fast path if not
tracing.

--
Brian Gerst
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286136 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromAndy Lutomirski <luto@amacapital.net>
Date2015-12-08 02:20 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDf6G-40S-5@gated-at.bofh.it>
In reply to#1286132
On Mon, Dec 7, 2015 at 4:54 PM, Brian Gerst <brgerst@gmail.com> wrote:
> On Mon, Dec 7, 2015 at 7:50 PM, Brian Gerst <brgerst@gmail.com> wrote:
>> On Mon, Dec 7, 2015 at 4:51 PM, Andy Lutomirski <luto@kernel.org> wrote:
>>> 64-bit syscalls currently have an optimization in which they are
>>> called with partial pt_regs.  A small handful require full pt_regs.
>>>
>>> In the 32-bit and compat cases, I cleaned this up by forcing full
>>> pt_regs for all syscalls.  The performance hit doesn't really matter.
>>>
>>> I want to clean up the 64-bit case as well, but I don't want to hurt
>>> fast path performance.  To do that, I want to force the syscalls
>>> that use pt_regs onto the slow path.  This will enable us to make
>>> slow path syscalls be real ABI-compliant C functions.
>>>
>>> Use the new syscall entry qualification machinery for this.
>>> stub_clone is now stub_clone/ptregs.
>>>
>>> The next patch will eliminate the stubs, and we'll just have
>>> sys_clone/ptregs.
>
> [Resend after gmail web interface fail]
>
> I've got an idea on how to do this without the duplicate syscall table.
>
> ptregs_foo:
>     leaq sys_foo(%rip), %rax
>     jmp stub_ptregs_64
>
> stub_ptregs_64:
>     testl $TS_EXTRAREGS, <current->ti_status>
>     jnz 1f
>     SAVE_EXTRA_REGS
>     call *%rax
>     RESTORE_EXTRA_REGS
>     ret
> 1:
>     call *%rax
>     ret
>
> This makes sure that the extra regs don't get saved a second time if
> coming in from the slow path, but preserves the fast path if not
> tracing.

I think there's value in having the entries in the table be genuine C
ABI-compliant function pointers.  In your example, it only barely
works -- you can call them from C only if you have TS_EXTRAREGS set
appropriately -- -otherwise you crash and burn.  That will break the
rest of the series.

We could adjust it a bit and check whether we're in C land (by
checking rsp for ts) and jump into the slow path if we aren't, but I'm
not sure this is a huge win.  It does save some rodata space by
avoiding duplicating the table.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286450 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromBrian Gerst <brgerst@gmail.com>
Date2015-12-08 14:10 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDqbM-2Nk-25@gated-at.bofh.it>
In reply to#1286136
On Mon, Dec 7, 2015 at 8:12 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Mon, Dec 7, 2015 at 4:54 PM, Brian Gerst <brgerst@gmail.com> wrote:
>> On Mon, Dec 7, 2015 at 7:50 PM, Brian Gerst <brgerst@gmail.com> wrote:
>>> On Mon, Dec 7, 2015 at 4:51 PM, Andy Lutomirski <luto@kernel.org> wrote:
>>>> 64-bit syscalls currently have an optimization in which they are
>>>> called with partial pt_regs.  A small handful require full pt_regs.
>>>>
>>>> In the 32-bit and compat cases, I cleaned this up by forcing full
>>>> pt_regs for all syscalls.  The performance hit doesn't really matter.
>>>>
>>>> I want to clean up the 64-bit case as well, but I don't want to hurt
>>>> fast path performance.  To do that, I want to force the syscalls
>>>> that use pt_regs onto the slow path.  This will enable us to make
>>>> slow path syscalls be real ABI-compliant C functions.
>>>>
>>>> Use the new syscall entry qualification machinery for this.
>>>> stub_clone is now stub_clone/ptregs.
>>>>
>>>> The next patch will eliminate the stubs, and we'll just have
>>>> sys_clone/ptregs.
>>
>> [Resend after gmail web interface fail]
>>
>> I've got an idea on how to do this without the duplicate syscall table.
>>
>> ptregs_foo:
>>     leaq sys_foo(%rip), %rax
>>     jmp stub_ptregs_64
>>
>> stub_ptregs_64:
>>     testl $TS_EXTRAREGS, <current->ti_status>
>>     jnz 1f
>>     SAVE_EXTRA_REGS
>>     call *%rax
>>     RESTORE_EXTRA_REGS
>>     ret
>> 1:
>>     call *%rax
>>     ret
>>
>> This makes sure that the extra regs don't get saved a second time if
>> coming in from the slow path, but preserves the fast path if not
>> tracing.
>
> I think there's value in having the entries in the table be genuine C
> ABI-compliant function pointers.  In your example, it only barely
> works -- you can call them from C only if you have TS_EXTRAREGS set
> appropriately -- -otherwise you crash and burn.  That will break the
> rest of the series.

I'm working on a full patch.  It will set the flag (renamed
TS_SLOWPATH) in do_syscall_64(), which is the only place these
functions can get called from C code.  Your changes already have it
set up so that the slow path saved these registers before calling any
C code.  Where else do you expect them to be called from?

> We could adjust it a bit and check whether we're in C land (by
> checking rsp for ts) and jump into the slow path if we aren't, but I'm
> not sure this is a huge win.  It does save some rodata space by
> avoiding duplicating the table.

The syscall table is huge.  545*8 bytes, over a full page.
Duplicating it for just a few different entries is wasteful.

--
Brian Gerst
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286777 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromIngo Molnar <mingo@kernel.org>
Date2015-12-08 20:00 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDvEu-60F-25@gated-at.bofh.it>
In reply to#1286450
* Brian Gerst <brgerst@gmail.com> wrote:

> > We could adjust it a bit and check whether we're in C land (by checking rsp 
> > for ts) and jump into the slow path if we aren't, but I'm not sure this is a 
> > huge win.  It does save some rodata space by avoiding duplicating the table.
> 
> The syscall table is huge.  545*8 bytes, over a full page. Duplicating it for 
> just a few different entries is wasteful.

Note that what matters more is cache footprint, not pure size: 1K of RAM overhead 
for something as fundamental as system calls is trivial cost.

So the questions to ask are along these lines:

 - what is the typical locality of access (do syscall numbers cluster in time and 
   space)

 - how frequently would the two tables be accessed (is one accessed less 
   frequently than the other?)

 - subsequently how does the effective cache footprint change with the 
   duplication?

it might still end up not being worth it - but it's not the RAM cost that is the 
main factor IMHO.

Thanks,

	Ingo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286868 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromAndy Lutomirski <luto@amacapital.net>
Date2015-12-08 23:00 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDysG-7MA-1@gated-at.bofh.it>
In reply to#1286777
On Tue, Dec 8, 2015 at 10:56 AM, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Brian Gerst <brgerst@gmail.com> wrote:
>
>> > We could adjust it a bit and check whether we're in C land (by checking rsp
>> > for ts) and jump into the slow path if we aren't, but I'm not sure this is a
>> > huge win.  It does save some rodata space by avoiding duplicating the table.
>>
>> The syscall table is huge.  545*8 bytes, over a full page. Duplicating it for
>> just a few different entries is wasteful.
>
> Note that what matters more is cache footprint, not pure size: 1K of RAM overhead
> for something as fundamental as system calls is trivial cost.
>
> So the questions to ask are along these lines:
>
>  - what is the typical locality of access (do syscall numbers cluster in time and
>    space)
>

I suspect that they do.  Web servers will call send over and over, for example.

>  - how frequently would the two tables be accessed (is one accessed less
>    frequently than the other?)

On setups that don't bail right away, the fast path table gets hit
most of the time.  On setups that do bail right away (context tracking
on, for example), we exclusively use the slow path table.

>
>  - subsequently how does the effective cache footprint change with the
>    duplication?

In the worst case (repeatedly forking, for example, but I doubt we
care about that case), the duplication adds one extra cacheline.

>
> it might still end up not being worth it - but it's not the RAM cost that is the
> main factor IMHO.

Agreed.

One option: borrow the high bit to indicate "needs ptregs".  This adds
a branch to both the fast path and the slow path, but it avoids the
cache hit.

Brian's approach gets the best of all worlds except that, if I
understand it right, it's a bit fragile.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1286133 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromBrian Gerst <brgerst@gmail.com>
Date2015-12-08 02:00 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDeNj-3D4-3@gated-at.bofh.it>
In reply to#1285988
On Mon, Dec 7, 2015 at 4:51 PM, Andy Lutomirski <luto@kernel.org> wrote:
> 64-bit syscalls currently have an optimization in which they are
> called with partial pt_regs.  A small handful require full pt_regs.
>
> In the 32-bit and compat cases, I cleaned this up by forcing full
> pt_regs for all syscalls.  The performance hit doesn't really matter.
>
> I want to clean up the 64-bit case as well, but I don't want to hurt
> fast path performance.  To do that, I want to force the syscalls
> that use pt_regs onto the slow path.  This will enable us to make
> slow path syscalls be real ABI-compliant C functions.
>
> Use the new syscall entry qualification machinery for this.
> stub_clone is now stub_clone/ptregs.
>
> The next patch will eliminate the stubs, and we'll just have
> sys_clone/ptregs.

I've got an idea on how to do this without the duplicate syscall table.

ptregs_foo:
    leaq sys_foo(%rip), %rax
    jmp stub_ptregs_64

stub_ptregs_64:
    testl $TS_EXTRAREGS, <current->ti_status>
    jnz 1f
    SAVE_EXTRA_REGS
    call *%rax
    RESTORE_EXTRA_REGS
    ret
1:
    call *%rax


--
Brian Gerst
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287106 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromBrian Gerst <brgerst@gmail.com>
Date2015-12-09 05:50 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDERs-3xo-13@gated-at.bofh.it>
In reply to#1285988
On Mon, Dec 7, 2015 at 4:51 PM, Andy Lutomirski <luto@kernel.org> wrote:
> 64-bit syscalls currently have an optimization in which they are
> called with partial pt_regs.  A small handful require full pt_regs.
>
> In the 32-bit and compat cases, I cleaned this up by forcing full
> pt_regs for all syscalls.  The performance hit doesn't really matter.
>
> I want to clean up the 64-bit case as well, but I don't want to hurt
> fast path performance.  To do that, I want to force the syscalls
> that use pt_regs onto the slow path.  This will enable us to make
> slow path syscalls be real ABI-compliant C functions.
>
> Use the new syscall entry qualification machinery for this.
> stub_clone is now stub_clone/ptregs.
>
> The next patch will eliminate the stubs, and we'll just have
> sys_clone/ptregs.
>
> Signed-off-by: Andy Lutomirski <luto@kernel.org>

Fails to boot, bisected to this patch:
[   32.675319] kernel BUG at kernel/auditsc.c:1504!
[   32.675325] invalid opcode: 0000 [#65] SMP
[   32.675328] Modules linked in:
[   32.675333] CPU: 1 PID: 216 Comm: systemd-cgroups Tainted: G      D
        4.3.0-rc4+ #7
[   32.675336] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[   32.675339] task: ffff880000075340 ti: ffff880036520000 task.ti:
ffff880036520000
[   32.675350] RIP: 0010:[<ffffffff8113d9ed>]  [<ffffffff8113d9ed>]
__audit_syscall_entry+0xcd/0xf0
[   32.675353] RSP: 0018:ffff880036523ef0  EFLAGS: 00010202
[   32.675355] RAX: 000000000000000c RBX: ffff8800797b3000 RCX: 00007ffef8504e88
[   32.675357] RDX: 000056172f37cfd0 RSI: 0000000000000000 RDI: 000000000000000c
[   32.675359] RBP: ffff880036523f00 R08: 0000000000000001 R09: ffff880000075340
[   32.675361] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
[   32.675363] R13: 00000000c000003e R14: 0000000000000001 R15: 0000000000001000
[   32.675380] FS:  00007f02b4ff48c0(0000) GS:ffff88007fc80000(0000)
knlGS:0000000000000000
[   32.675383] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[   32.675385] CR2: 00007f93d47ea0e0 CR3: 0000000036aa9000 CR4: 00000000000006e0
[   32.675391] Stack:
[   32.675396]  ffff880036523f58 0000000000000000 ffff880036523f10
ffffffff8100321b
[   32.675401]  ffff880036523f48 ffffffff81003ad0 000056172f374040
00007f93d45c9990
[   32.675404]  0000000000000001 0000000000000001 0000000000001000
000000000000000a
[   32.675405] Call Trace:
[   32.675414]  [<ffffffff8100321b>] do_audit_syscall_entry+0x4b/0x70
[   32.675420]  [<ffffffff81003ad0>] syscall_trace_enter_phase2+0x110/0x1d0
[   32.675425]  [<ffffffff81761d94>] tracesys+0x3a/0x96
[   32.675464] Code: 00 00 00 00 e8 a5 e0 fc ff c7 43 04 01 00 00 00
48 89 43 18 48 89 53 20 44 89 63 0c c7 83 94 02 00 00 00 00 00 00 5b
41 5c 5d c3 <0f> 0b 48 c7 43 50 00 00 00 00 48 c7 c2 60 b4 c5 81 48 89
de 4c
[   32.675469] RIP  [<ffffffff8113d9ed>] __audit_syscall_entry+0xcd/0xf0
[   32.675471]  RSP <ffff880036523ef0>

--
Brian Gerst
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287128 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromAndy Lutomirski <luto@amacapital.net>
Date2015-12-09 06:50 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDFNw-4bT-3@gated-at.bofh.it>
In reply to#1287106
On Tue, Dec 8, 2015 at 8:43 PM, Brian Gerst <brgerst@gmail.com> wrote:
> On Mon, Dec 7, 2015 at 4:51 PM, Andy Lutomirski <luto@kernel.org> wrote:
>> 64-bit syscalls currently have an optimization in which they are
>> called with partial pt_regs.  A small handful require full pt_regs.
>>
>> In the 32-bit and compat cases, I cleaned this up by forcing full
>> pt_regs for all syscalls.  The performance hit doesn't really matter.
>>
>> I want to clean up the 64-bit case as well, but I don't want to hurt
>> fast path performance.  To do that, I want to force the syscalls
>> that use pt_regs onto the slow path.  This will enable us to make
>> slow path syscalls be real ABI-compliant C functions.
>>
>> Use the new syscall entry qualification machinery for this.
>> stub_clone is now stub_clone/ptregs.
>>
>> The next patch will eliminate the stubs, and we'll just have
>> sys_clone/ptregs.
>>
>> Signed-off-by: Andy Lutomirski <luto@kernel.org>
>
> Fails to boot, bisected to this patch:
> [   32.675319] kernel BUG at kernel/auditsc.c:1504!
> [   32.675325] invalid opcode: 0000 [#65] SMP
> [   32.675328] Modules linked in:
> [   32.675333] CPU: 1 PID: 216 Comm: systemd-cgroups Tainted: G      D
>         4.3.0-rc4+ #7
> [   32.675336] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
> [   32.675339] task: ffff880000075340 ti: ffff880036520000 task.ti:
> ffff880036520000
> [   32.675350] RIP: 0010:[<ffffffff8113d9ed>]  [<ffffffff8113d9ed>]
> __audit_syscall_entry+0xcd/0xf0
> [   32.675353] RSP: 0018:ffff880036523ef0  EFLAGS: 00010202
> [   32.675355] RAX: 000000000000000c RBX: ffff8800797b3000 RCX: 00007ffef8504e88
> [   32.675357] RDX: 000056172f37cfd0 RSI: 0000000000000000 RDI: 000000000000000c
> [   32.675359] RBP: ffff880036523f00 R08: 0000000000000001 R09: ffff880000075340
> [   32.675361] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
> [   32.675363] R13: 00000000c000003e R14: 0000000000000001 R15: 0000000000001000
> [   32.675380] FS:  00007f02b4ff48c0(0000) GS:ffff88007fc80000(0000)
> knlGS:0000000000000000
> [   32.675383] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> [   32.675385] CR2: 00007f93d47ea0e0 CR3: 0000000036aa9000 CR4: 00000000000006e0
> [   32.675391] Stack:
> [   32.675396]  ffff880036523f58 0000000000000000 ffff880036523f10
> ffffffff8100321b
> [   32.675401]  ffff880036523f48 ffffffff81003ad0 000056172f374040
> 00007f93d45c9990
> [   32.675404]  0000000000000001 0000000000000001 0000000000001000
> 000000000000000a
> [   32.675405] Call Trace:
> [   32.675414]  [<ffffffff8100321b>] do_audit_syscall_entry+0x4b/0x70
> [   32.675420]  [<ffffffff81003ad0>] syscall_trace_enter_phase2+0x110/0x1d0
> [   32.675425]  [<ffffffff81761d94>] tracesys+0x3a/0x96
> [   32.675464] Code: 00 00 00 00 e8 a5 e0 fc ff c7 43 04 01 00 00 00
> 48 89 43 18 48 89 53 20 44 89 63 0c c7 83 94 02 00 00 00 00 00 00 5b
> 41 5c 5d c3 <0f> 0b 48 c7 43 50 00 00 00 00 48 c7 c2 60 b4 c5 81 48 89
> de 4c
> [   32.675469] RIP  [<ffffffff8113d9ed>] __audit_syscall_entry+0xcd/0xf0
> [   32.675471]  RSP <ffff880036523ef0>

I'm not reproducing this, even with audit manually enabled.  Can you
send a .config?

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287143 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromAndy Lutomirski <luto@amacapital.net>
Date2015-12-09 07:30 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDGqd-4EB-15@gated-at.bofh.it>
In reply to#1287128
On Tue, Dec 8, 2015 at 9:45 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Tue, Dec 8, 2015 at 8:43 PM, Brian Gerst <brgerst@gmail.com> wrote:
>> On Mon, Dec 7, 2015 at 4:51 PM, Andy Lutomirski <luto@kernel.org> wrote:
>>> 64-bit syscalls currently have an optimization in which they are
>>> called with partial pt_regs.  A small handful require full pt_regs.
>>>
>>> In the 32-bit and compat cases, I cleaned this up by forcing full
>>> pt_regs for all syscalls.  The performance hit doesn't really matter.
>>>
>>> I want to clean up the 64-bit case as well, but I don't want to hurt
>>> fast path performance.  To do that, I want to force the syscalls
>>> that use pt_regs onto the slow path.  This will enable us to make
>>> slow path syscalls be real ABI-compliant C functions.
>>>
>>> Use the new syscall entry qualification machinery for this.
>>> stub_clone is now stub_clone/ptregs.
>>>
>>> The next patch will eliminate the stubs, and we'll just have
>>> sys_clone/ptregs.
>>>
>>> Signed-off-by: Andy Lutomirski <luto@kernel.org>
>>
>> Fails to boot, bisected to this patch:
>> [   32.675319] kernel BUG at kernel/auditsc.c:1504!
>> [   32.675325] invalid opcode: 0000 [#65] SMP
>> [   32.675328] Modules linked in:
>> [   32.675333] CPU: 1 PID: 216 Comm: systemd-cgroups Tainted: G      D
>>         4.3.0-rc4+ #7
>> [   32.675336] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
>> [   32.675339] task: ffff880000075340 ti: ffff880036520000 task.ti:
>> ffff880036520000
>> [   32.675350] RIP: 0010:[<ffffffff8113d9ed>]  [<ffffffff8113d9ed>]
>> __audit_syscall_entry+0xcd/0xf0
>> [   32.675353] RSP: 0018:ffff880036523ef0  EFLAGS: 00010202
>> [   32.675355] RAX: 000000000000000c RBX: ffff8800797b3000 RCX: 00007ffef8504e88
>> [   32.675357] RDX: 000056172f37cfd0 RSI: 0000000000000000 RDI: 000000000000000c
>> [   32.675359] RBP: ffff880036523f00 R08: 0000000000000001 R09: ffff880000075340
>> [   32.675361] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
>> [   32.675363] R13: 00000000c000003e R14: 0000000000000001 R15: 0000000000001000
>> [   32.675380] FS:  00007f02b4ff48c0(0000) GS:ffff88007fc80000(0000)
>> knlGS:0000000000000000
>> [   32.675383] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
>> [   32.675385] CR2: 00007f93d47ea0e0 CR3: 0000000036aa9000 CR4: 00000000000006e0
>> [   32.675391] Stack:
>> [   32.675396]  ffff880036523f58 0000000000000000 ffff880036523f10
>> ffffffff8100321b
>> [   32.675401]  ffff880036523f48 ffffffff81003ad0 000056172f374040
>> 00007f93d45c9990
>> [   32.675404]  0000000000000001 0000000000000001 0000000000001000
>> 000000000000000a
>> [   32.675405] Call Trace:
>> [   32.675414]  [<ffffffff8100321b>] do_audit_syscall_entry+0x4b/0x70
>> [   32.675420]  [<ffffffff81003ad0>] syscall_trace_enter_phase2+0x110/0x1d0
>> [   32.675425]  [<ffffffff81761d94>] tracesys+0x3a/0x96
>> [   32.675464] Code: 00 00 00 00 e8 a5 e0 fc ff c7 43 04 01 00 00 00
>> 48 89 43 18 48 89 53 20 44 89 63 0c c7 83 94 02 00 00 00 00 00 00 5b
>> 41 5c 5d c3 <0f> 0b 48 c7 43 50 00 00 00 00 48 c7 c2 60 b4 c5 81 48 89
>> de 4c
>> [   32.675469] RIP  [<ffffffff8113d9ed>] __audit_syscall_entry+0xcd/0xf0
>> [   32.675471]  RSP <ffff880036523ef0>
>
> I'm not reproducing this, even with audit manually enabled.  Can you
> send a .config?

Never mind, I found the bug by inspection.  I'll send a fixed up
series tomorrow.

Can you send the boot failure you got with the full series applied,
though?  I think that the bug I found is only triggerable part-way
through the series -- I think I inadvertently fixed it later on.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287474 — Re: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path

FromBrian Gerst <brgerst@gmail.com>
Date2015-12-09 14:00 +0100
SubjectRe: [PATCH 07/12] x86/entry/64: Always run ptregs-using syscalls on the slow path
Message-ID<qDMvD-51-1@gated-at.bofh.it>
In reply to#1287143
On Wed, Dec 9, 2015 at 1:21 AM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Tue, Dec 8, 2015 at 9:45 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>> On Tue, Dec 8, 2015 at 8:43 PM, Brian Gerst <brgerst@gmail.com> wrote:
>>> On Mon, Dec 7, 2015 at 4:51 PM, Andy Lutomirski <luto@kernel.org> wrote:
>>>> 64-bit syscalls currently have an optimization in which they are
>>>> called with partial pt_regs.  A small handful require full pt_regs.
>>>>
>>>> In the 32-bit and compat cases, I cleaned this up by forcing full
>>>> pt_regs for all syscalls.  The performance hit doesn't really matter.
>>>>
>>>> I want to clean up the 64-bit case as well, but I don't want to hurt
>>>> fast path performance.  To do that, I want to force the syscalls
>>>> that use pt_regs onto the slow path.  This will enable us to make
>>>> slow path syscalls be real ABI-compliant C functions.
>>>>
>>>> Use the new syscall entry qualification machinery for this.
>>>> stub_clone is now stub_clone/ptregs.
>>>>
>>>> The next patch will eliminate the stubs, and we'll just have
>>>> sys_clone/ptregs.
>>>>
>>>> Signed-off-by: Andy Lutomirski <luto@kernel.org>
>>>
>>> Fails to boot, bisected to this patch:
>>> [   32.675319] kernel BUG at kernel/auditsc.c:1504!
>>> [   32.675325] invalid opcode: 0000 [#65] SMP
>>> [   32.675328] Modules linked in:
>>> [   32.675333] CPU: 1 PID: 216 Comm: systemd-cgroups Tainted: G      D
>>>         4.3.0-rc4+ #7
>>> [   32.675336] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
>>> [   32.675339] task: ffff880000075340 ti: ffff880036520000 task.ti:
>>> ffff880036520000
>>> [   32.675350] RIP: 0010:[<ffffffff8113d9ed>]  [<ffffffff8113d9ed>]
>>> __audit_syscall_entry+0xcd/0xf0
>>> [   32.675353] RSP: 0018:ffff880036523ef0  EFLAGS: 00010202
>>> [   32.675355] RAX: 000000000000000c RBX: ffff8800797b3000 RCX: 00007ffef8504e88
>>> [   32.675357] RDX: 000056172f37cfd0 RSI: 0000000000000000 RDI: 000000000000000c
>>> [   32.675359] RBP: ffff880036523f00 R08: 0000000000000001 R09: ffff880000075340
>>> [   32.675361] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
>>> [   32.675363] R13: 00000000c000003e R14: 0000000000000001 R15: 0000000000001000
>>> [   32.675380] FS:  00007f02b4ff48c0(0000) GS:ffff88007fc80000(0000)
>>> knlGS:0000000000000000
>>> [   32.675383] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
>>> [   32.675385] CR2: 00007f93d47ea0e0 CR3: 0000000036aa9000 CR4: 00000000000006e0
>>> [   32.675391] Stack:
>>> [   32.675396]  ffff880036523f58 0000000000000000 ffff880036523f10
>>> ffffffff8100321b
>>> [   32.675401]  ffff880036523f48 ffffffff81003ad0 000056172f374040
>>> 00007f93d45c9990
>>> [   32.675404]  0000000000000001 0000000000000001 0000000000001000
>>> 000000000000000a
>>> [   32.675405] Call Trace:
>>> [   32.675414]  [<ffffffff8100321b>] do_audit_syscall_entry+0x4b/0x70
>>> [   32.675420]  [<ffffffff81003ad0>] syscall_trace_enter_phase2+0x110/0x1d0
>>> [   32.675425]  [<ffffffff81761d94>] tracesys+0x3a/0x96
>>> [   32.675464] Code: 00 00 00 00 e8 a5 e0 fc ff c7 43 04 01 00 00 00
>>> 48 89 43 18 48 89 53 20 44 89 63 0c c7 83 94 02 00 00 00 00 00 00 5b
>>> 41 5c 5d c3 <0f> 0b 48 c7 43 50 00 00 00 00 48 c7 c2 60 b4 c5 81 48 89
>>> de 4c
>>> [   32.675469] RIP  [<ffffffff8113d9ed>] __audit_syscall_entry+0xcd/0xf0
>>> [   32.675471]  RSP <ffff880036523ef0>
>>
>> I'm not reproducing this, even with audit manually enabled.  Can you
>> send a .config?
>
> Never mind, I found the bug by inspection.  I'll send a fixed up
> series tomorrow.
>
> Can you send the boot failure you got with the full series applied,
> though?  I think that the bug I found is only triggerable part-way
> through the series -- I think I inadvertently fixed it later on.

I can't reproduce it now.  It was a hang, or I just didn't get the
oops displayed on the screen.  Could have been somethng unrelated.

--
Brian Gerst
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287479 — [PATCH] x86/entry/64: Remove duplicate syscall table for fast path

FromBrian Gerst <brgerst@gmail.com>
Date2015-12-09 14:10 +0100
Subject[PATCH] x86/entry/64: Remove duplicate syscall table for fast path
Message-ID<qDMFk-nF-13@gated-at.bofh.it>
In reply to#1287143
Instead of using a duplicate syscall table for the fast path, create stubs for
the syscalls that need pt_regs that save the extra registers if a flag for the
slow path is not set.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
To: Andy Lutomirski <luto@amacapital.net>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: the arch/x86 maintainers <x86@kernel.org>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
---

Applies on top of Andy's syscall cleanup series.


 arch/x86/entry/calling.h           | 32 ++++++++++++++++----------------
 arch/x86/entry/common.c            |  4 ++++
 arch/x86/entry/entry_64.S          | 36 +++++++++++++++++++++++++++++-------
 arch/x86/entry/syscall_64.c        | 25 +++++--------------------
 arch/x86/include/asm/thread_info.h |  1 +
 5 files changed, 55 insertions(+), 43 deletions(-)

diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
index e32206e..7c58bd2 100644
--- a/arch/x86/entry/calling.h
+++ b/arch/x86/entry/calling.h
@@ -129,22 +129,22 @@ For 32-bit we have the following conventions - kernel is built with
 	SAVE_C_REGS_HELPER 0, 0, 0, 1, 0
 	.endm
 
-	.macro SAVE_EXTRA_REGS offset=0
-	movq %r15, 0*8+\offset(%rsp)
-	movq %r14, 1*8+\offset(%rsp)
-	movq %r13, 2*8+\offset(%rsp)
-	movq %r12, 3*8+\offset(%rsp)
-	movq %rbp, 4*8+\offset(%rsp)
-	movq %rbx, 5*8+\offset(%rsp)
-	.endm
-
-	.macro RESTORE_EXTRA_REGS offset=0
-	movq 0*8+\offset(%rsp), %r15
-	movq 1*8+\offset(%rsp), %r14
-	movq 2*8+\offset(%rsp), %r13
-	movq 3*8+\offset(%rsp), %r12
-	movq 4*8+\offset(%rsp), %rbp
-	movq 5*8+\offset(%rsp), %rbx
+	.macro SAVE_EXTRA_REGS offset=0 base=rsp
+	movq %r15, 0*8+\offset(%\base)
+	movq %r14, 1*8+\offset(%\base)
+	movq %r13, 2*8+\offset(%\base)
+	movq %r12, 3*8+\offset(%\base)
+	movq %rbp, 4*8+\offset(%\base)
+	movq %rbx, 5*8+\offset(%\base)
+	.endm
+
+	.macro RESTORE_EXTRA_REGS offset=0 base=rsp
+	movq 0*8+\offset(%\base), %r15
+	movq 1*8+\offset(%\base), %r14
+	movq 2*8+\offset(%\base), %r13
+	movq 3*8+\offset(%\base), %r12
+	movq 4*8+\offset(%\base), %rbp
+	movq 5*8+\offset(%\base), %rbx
 	.endm
 
 	.macro ZERO_EXTRA_REGS
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 016ac47..4381aca 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -342,6 +342,8 @@ __visible void do_syscall_64(struct pt_regs *regs)
 	struct thread_info *ti = pt_regs_to_thread_info(regs);
 	unsigned long nr = regs->orig_ax;
 
+	ti->status |= TS_SLOWPATH;
+
 	enter_from_user_mode();
 	local_irq_enable();
 
@@ -360,6 +362,8 @@ __visible void do_syscall_64(struct pt_regs *regs)
 	}
 
 	syscall_return_slowpath(regs);
+
+	ti->status &= ~TS_SLOWPATH;
 }
 #endif
 
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 1ab5362..5852ec6 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -188,7 +188,7 @@ entry_SYSCALL_64_fastpath:
 #endif
 	ja	1f				/* return -ENOSYS (already in pt_regs->ax) */
 	movq	%r10, %rcx
-	call	*sys_call_table_fastpath_64(, %rax, 8)
+	call	*sys_call_table(, %rax, 8)
 	movq	%rax, RAX(%rsp)
 1:
 
@@ -306,15 +306,37 @@ END(entry_SYSCALL_64)
 
 ENTRY(stub_ptregs_64)
 	/*
-	 * Syscalls marked as needing ptregs that go through the fast path
-	 * land here.  We transfer to the slow path.
+	 * Syscalls marked as needing ptregs land here.
+	 * If we are on the fast path, we need to save the extra regs.
+	 * If we are on the slow path, the extra regs are already saved.
 	 */
-	DISABLE_INTERRUPTS(CLBR_NONE)
-	TRACE_IRQS_OFF
-	addq	$8, %rsp
-	jmp	entry_SYSCALL64_slow_path
+	movq	PER_CPU_VAR(cpu_current_top_of_stack), %r10
+	testl	$TS_SLOWPATH, ASM_THREAD_INFO(TI_status, %r10, 0)
+	jnz	1f
+	subq	$SIZEOF_PTREGS, %r10
+	SAVE_EXTRA_REGS base=r10
+	movq	%r10, %rbx
+	call	*%rax
+	movq	%rbx, %r10
+	RESTORE_EXTRA_REGS base=r10
+	ret
+1:
+	jmp	*%rax
 END(stub_ptregs_64)
 
+.macro ptregs_stub func
+ENTRY(ptregs_\func)
+	leaq	\func(%rip), %rax
+	jmp	stub_ptregs_64
+END(ptregs_\func)
+.endm
+
+#define __SYSCALL_64_QUAL_(sym)
+#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_stub sym
+
+#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(sym)
+#include <asm/syscalls_64.h>
+
 /*
  * A newly forked process directly context switches into this address.
  *
diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
index 601745c..9dbc5ab 100644
--- a/arch/x86/entry/syscall_64.c
+++ b/arch/x86/entry/syscall_64.c
@@ -6,11 +6,14 @@
 #include <asm/asm-offsets.h>
 #include <asm/syscall.h>
 
-#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
+#define __SYSCALL_64_QUAL_(sym) sym
+#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_##sym
+
+#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long __SYSCALL_64_QUAL_##qual(sym)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 #include <asm/syscalls_64.h>
 #undef __SYSCALL_64
 
-#define __SYSCALL_64(nr, sym, qual) [nr] = sym,
+#define __SYSCALL_64(nr, sym, qual) [nr] = __SYSCALL_64_QUAL_##qual(sym),
 
 extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 
@@ -22,21 +25,3 @@ asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
 	[0 ... __NR_syscall_max] = &sys_ni_syscall,
 #include <asm/syscalls_64.h>
 };
-
-#undef __SYSCALL_64
-
-extern long stub_ptregs_64(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
-
-#define __SYSCALL_64_QUAL_(nr, sym) [nr] = sym,
-#define __SYSCALL_64_QUAL_ptregs(nr, sym) [nr] = stub_ptregs_64,
-
-#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(nr, sym)
-
-asmlinkage const sys_call_ptr_t sys_call_table_fastpath_64[__NR_syscall_max+1] = {
-	/*
-	 * Smells like a compiler bug -- it doesn't work
-	 * when the & below is removed.
-	 */
-	[0 ... __NR_syscall_max] = &sys_ni_syscall,
-#include <asm/syscalls_64.h>
-};
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index ae210d6..358e3a9 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -229,6 +229,7 @@ static inline unsigned long current_stack_pointer(void)
  * ever touches our thread-synchronous status, so we don't
  * have to worry about atomic accesses.
  */
+#define TS_SLOWPATH		0x0001	/* syscall slowpath (64BIT) */
 #define TS_COMPAT		0x0002	/* 32bit syscall active (64BIT)*/
 #define TS_RESTORE_SIGMASK	0x0008	/* restore signal mask in do_signal() */
 
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287740 — Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path

FromAndy Lutomirski <luto@amacapital.net>
Date2015-12-09 20:00 +0100
SubjectRe: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path
Message-ID<qDS82-3Fq-17@gated-at.bofh.it>
In reply to#1287479
On Wed, Dec 9, 2015 at 5:02 AM, Brian Gerst <brgerst@gmail.com> wrote:
> Instead of using a duplicate syscall table for the fast path, create stubs for
> the syscalls that need pt_regs that save the extra registers if a flag for the
> slow path is not set.
>
> Signed-off-by: Brian Gerst <brgerst@gmail.com>
> To: Andy Lutomirski <luto@amacapital.net>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: the arch/x86 maintainers <x86@kernel.org>
> Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Frédéric Weisbecker <fweisbec@gmail.com>
> Cc: Denys Vlasenko <dvlasenk@redhat.com>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> ---
>
> Applies on top of Andy's syscall cleanup series.

A couple questions:

> @@ -306,15 +306,37 @@ END(entry_SYSCALL_64)
>
>  ENTRY(stub_ptregs_64)
>         /*
> -        * Syscalls marked as needing ptregs that go through the fast path
> -        * land here.  We transfer to the slow path.
> +        * Syscalls marked as needing ptregs land here.
> +        * If we are on the fast path, we need to save the extra regs.
> +        * If we are on the slow path, the extra regs are already saved.
>          */
> -       DISABLE_INTERRUPTS(CLBR_NONE)
> -       TRACE_IRQS_OFF
> -       addq    $8, %rsp
> -       jmp     entry_SYSCALL64_slow_path
> +       movq    PER_CPU_VAR(cpu_current_top_of_stack), %r10
> +       testl   $TS_SLOWPATH, ASM_THREAD_INFO(TI_status, %r10, 0)
> +       jnz     1f

OK (but see below), but why not do:

addq $8, %rsp
jmp entry_SYSCALL64_slow_path

here instead of the stack munging below?

> +       subq    $SIZEOF_PTREGS, %r10
> +       SAVE_EXTRA_REGS base=r10
> +       movq    %r10, %rbx
> +       call    *%rax
> +       movq    %rbx, %r10
> +       RESTORE_EXTRA_REGS base=r10
> +       ret
> +1:
> +       jmp     *%rax
>  END(stub_ptregs_64)

Also, can we not get away with keying off rip or rsp instead of
ti->status?  That should be faster and less magical IMO.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287858 — Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path

FromBrian Gerst <brgerst@gmail.com>
Date2015-12-09 22:10 +0100
SubjectRe: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path
Message-ID<qDU9R-5bQ-19@gated-at.bofh.it>
In reply to#1287740
On Wed, Dec 9, 2015 at 1:53 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Wed, Dec 9, 2015 at 5:02 AM, Brian Gerst <brgerst@gmail.com> wrote:
>> Instead of using a duplicate syscall table for the fast path, create stubs for
>> the syscalls that need pt_regs that save the extra registers if a flag for the
>> slow path is not set.
>>
>> Signed-off-by: Brian Gerst <brgerst@gmail.com>
>> To: Andy Lutomirski <luto@amacapital.net>
>> Cc: Andy Lutomirski <luto@kernel.org>
>> Cc: the arch/x86 maintainers <x86@kernel.org>
>> Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
>> Cc: Borislav Petkov <bp@alien8.de>
>> Cc: Frédéric Weisbecker <fweisbec@gmail.com>
>> Cc: Denys Vlasenko <dvlasenk@redhat.com>
>> Cc: Linus Torvalds <torvalds@linux-foundation.org>
>> ---
>>
>> Applies on top of Andy's syscall cleanup series.
>
> A couple questions:
>
>> @@ -306,15 +306,37 @@ END(entry_SYSCALL_64)
>>
>>  ENTRY(stub_ptregs_64)
>>         /*
>> -        * Syscalls marked as needing ptregs that go through the fast path
>> -        * land here.  We transfer to the slow path.
>> +        * Syscalls marked as needing ptregs land here.
>> +        * If we are on the fast path, we need to save the extra regs.
>> +        * If we are on the slow path, the extra regs are already saved.
>>          */
>> -       DISABLE_INTERRUPTS(CLBR_NONE)
>> -       TRACE_IRQS_OFF
>> -       addq    $8, %rsp
>> -       jmp     entry_SYSCALL64_slow_path
>> +       movq    PER_CPU_VAR(cpu_current_top_of_stack), %r10
>> +       testl   $TS_SLOWPATH, ASM_THREAD_INFO(TI_status, %r10, 0)
>> +       jnz     1f
>
> OK (but see below), but why not do:
>
> addq $8, %rsp
> jmp entry_SYSCALL64_slow_path

I've always been adverse to doing things like that because it breaks
call/return branch prediction.
Also, are there any side effects to calling enter_from_user_mode()
more than once?

> here instead of the stack munging below?
>
>> +       subq    $SIZEOF_PTREGS, %r10
>> +       SAVE_EXTRA_REGS base=r10
>> +       movq    %r10, %rbx
>> +       call    *%rax
>> +       movq    %rbx, %r10
>> +       RESTORE_EXTRA_REGS base=r10
>> +       ret
>> +1:
>> +       jmp     *%rax
>>  END(stub_ptregs_64)

After some thought, that can be simplified.  It's only executed on the
fast path, so pt_regs is at 8(%rsp).

> Also, can we not get away with keying off rip or rsp instead of
> ti->status?  That should be faster and less magical IMO.

Checking if the return address is the instruction after the fast path
dispatch would work.

Simplified version:
ENTRY(stub_ptregs_64)
    cmpl $fast_path_return, (%rsp)
    jne 1f
    SAVE_EXTRA_REGS offset=8
    call *%rax
    RESTORE_EXTRA_REGS offset=8
    ret
1:
    jmp *%rax
END(stub_ptregs_64)

--
Brian Gerst
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287871 — Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path

FromAndy Lutomirski <luto@amacapital.net>
Date2015-12-09 22:20 +0100
SubjectRe: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path
Message-ID<qDUjx-5eV-19@gated-at.bofh.it>
In reply to#1287858
On Wed, Dec 9, 2015 at 1:08 PM, Brian Gerst <brgerst@gmail.com> wrote:
> On Wed, Dec 9, 2015 at 1:53 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>> On Wed, Dec 9, 2015 at 5:02 AM, Brian Gerst <brgerst@gmail.com> wrote:
>>> Instead of using a duplicate syscall table for the fast path, create stubs for
>>> the syscalls that need pt_regs that save the extra registers if a flag for the
>>> slow path is not set.
>>>
>>> Signed-off-by: Brian Gerst <brgerst@gmail.com>
>>> To: Andy Lutomirski <luto@amacapital.net>
>>> Cc: Andy Lutomirski <luto@kernel.org>
>>> Cc: the arch/x86 maintainers <x86@kernel.org>
>>> Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
>>> Cc: Borislav Petkov <bp@alien8.de>
>>> Cc: Frédéric Weisbecker <fweisbec@gmail.com>
>>> Cc: Denys Vlasenko <dvlasenk@redhat.com>
>>> Cc: Linus Torvalds <torvalds@linux-foundation.org>
>>> ---
>>>
>>> Applies on top of Andy's syscall cleanup series.
>>
>> A couple questions:
>>
>>> @@ -306,15 +306,37 @@ END(entry_SYSCALL_64)
>>>
>>>  ENTRY(stub_ptregs_64)
>>>         /*
>>> -        * Syscalls marked as needing ptregs that go through the fast path
>>> -        * land here.  We transfer to the slow path.
>>> +        * Syscalls marked as needing ptregs land here.
>>> +        * If we are on the fast path, we need to save the extra regs.
>>> +        * If we are on the slow path, the extra regs are already saved.
>>>          */
>>> -       DISABLE_INTERRUPTS(CLBR_NONE)
>>> -       TRACE_IRQS_OFF
>>> -       addq    $8, %rsp
>>> -       jmp     entry_SYSCALL64_slow_path
>>> +       movq    PER_CPU_VAR(cpu_current_top_of_stack), %r10
>>> +       testl   $TS_SLOWPATH, ASM_THREAD_INFO(TI_status, %r10, 0)
>>> +       jnz     1f
>>
>> OK (but see below), but why not do:
>>
>> addq $8, %rsp
>> jmp entry_SYSCALL64_slow_path
>
> I've always been adverse to doing things like that because it breaks
> call/return branch prediction.

I'd agree with you there except that the syscalls in question really
don't matter for performance enough that we should worry about a
handful of cycles from a return misprediction.  We're still avoiding
IRET regardless (to the extent possible), and that was always the
major factor.

> Also, are there any side effects to calling enter_from_user_mode()
> more than once?

A warning that invariants are broken if you have an appropriately
configured kernel.

>
>> here instead of the stack munging below?
>>
>>> +       subq    $SIZEOF_PTREGS, %r10
>>> +       SAVE_EXTRA_REGS base=r10
>>> +       movq    %r10, %rbx
>>> +       call    *%rax
>>> +       movq    %rbx, %r10
>>> +       RESTORE_EXTRA_REGS base=r10
>>> +       ret
>>> +1:
>>> +       jmp     *%rax
>>>  END(stub_ptregs_64)
>
> After some thought, that can be simplified.  It's only executed on the
> fast path, so pt_regs is at 8(%rsp).
>
>> Also, can we not get away with keying off rip or rsp instead of
>> ti->status?  That should be faster and less magical IMO.
>
> Checking if the return address is the instruction after the fast path
> dispatch would work.
>
> Simplified version:
> ENTRY(stub_ptregs_64)
>     cmpl $fast_path_return, (%rsp)

Does that instruction actually work the way you want it to?  (Does it
link?)  I think you might need to use leaq the way I did in my patch.

>     jne 1f
>     SAVE_EXTRA_REGS offset=8
>     call *%rax
>     RESTORE_EXTRA_REGS offset=8
>     ret
> 1:
>     jmp *%rax
> END(stub_ptregs_64)

This'll work, I think, but I still think I prefer keeping as much
complexity as possible in the slow path.  I could be convinced
otherwise, though -- this variant is reasonably clean.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1288067 — Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path

FromAndy Lutomirski <luto@amacapital.net>
Date2015-12-10 01:00 +0100
SubjectRe: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path
Message-ID<qDWOm-6Hc-21@gated-at.bofh.it>
In reply to#1287871
On Wed, Dec 9, 2015 at 1:15 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Wed, Dec 9, 2015 at 1:08 PM, Brian Gerst <brgerst@gmail.com> wrote:
>> Simplified version:
>> ENTRY(stub_ptregs_64)
>>     cmpl $fast_path_return, (%rsp)
>
> Does that instruction actually work the way you want it to?  (Does it
> link?)  I think you might need to use leaq the way I did in my patch.
>
>>     jne 1f
>>     SAVE_EXTRA_REGS offset=8
>>     call *%rax
>>     RESTORE_EXTRA_REGS offset=8
>>     ret
>> 1:
>>     jmp *%rax
>> END(stub_ptregs_64)
>
> This'll work, I think, but I still think I prefer keeping as much
> complexity as possible in the slow path.  I could be convinced
> otherwise, though -- this variant is reasonably clean.

On further reflection, there's at least one functional difference.
With my variant, modifying pt_regs from sys_foo/ptregs is safe.  In
your variant, it's unsafe unless force_iret() is called.  I don't know
whether we care.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1288212 — Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path

FromBrian Gerst <brgerst@gmail.com>
Date2015-12-10 06:50 +0100
SubjectRe: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path
Message-ID<qE2h5-1SS-9@gated-at.bofh.it>
In reply to#1288067
On Wed, Dec 9, 2015 at 6:50 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Wed, Dec 9, 2015 at 1:15 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>> On Wed, Dec 9, 2015 at 1:08 PM, Brian Gerst <brgerst@gmail.com> wrote:
>>> Simplified version:
>>> ENTRY(stub_ptregs_64)
>>>     cmpl $fast_path_return, (%rsp)
>>
>> Does that instruction actually work the way you want it to?  (Does it
>> link?)  I think you might need to use leaq the way I did in my patch.

It should have been cmpq.  leaq isn't necessary, since immediates are
sign-extended to 64-bit.

>>>     jne 1f
>>>     SAVE_EXTRA_REGS offset=8
>>>     call *%rax
>>>     RESTORE_EXTRA_REGS offset=8
>>>     ret
>>> 1:
>>>     jmp *%rax
>>> END(stub_ptregs_64)
>>
>> This'll work, I think, but I still think I prefer keeping as much
>> complexity as possible in the slow path.  I could be convinced
>> otherwise, though -- this variant is reasonably clean.
>
> On further reflection, there's at least one functional difference.
> With my variant, modifying pt_regs from sys_foo/ptregs is safe.  In
> your variant, it's unsafe unless force_iret() is called.  I don't know
> whether we care.

I can go either way at this point.  My main concern was getting rid of
the duplicate table.

--
Brian Gerst
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1288214 — Re: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path

FromAndy Lutomirski <luto@amacapital.net>
Date2015-12-10 07:00 +0100
SubjectRe: [PATCH] x86/entry/64: Remove duplicate syscall table for fast path
Message-ID<qE2qK-1W9-3@gated-at.bofh.it>
In reply to#1288212
On Wed, Dec 9, 2015 at 9:42 PM, Brian Gerst <brgerst@gmail.com> wrote:
> On Wed, Dec 9, 2015 at 6:50 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>> On Wed, Dec 9, 2015 at 1:15 PM, Andy Lutomirski <luto@amacapital.net> wrote:
>>> On Wed, Dec 9, 2015 at 1:08 PM, Brian Gerst <brgerst@gmail.com> wrote:
>>>> Simplified version:
>>>> ENTRY(stub_ptregs_64)
>>>>     cmpl $fast_path_return, (%rsp)
>>>
>>> Does that instruction actually work the way you want it to?  (Does it
>>> link?)  I think you might need to use leaq the way I did in my patch.
>
> It should have been cmpq.  leaq isn't necessary, since immediates are
> sign-extended to 64-bit.

Right, I always forget that they're sign-extended and not zero-extended.

I folded that bit in to my queue.

>
>>>>     jne 1f
>>>>     SAVE_EXTRA_REGS offset=8
>>>>     call *%rax
>>>>     RESTORE_EXTRA_REGS offset=8
>>>>     ret
>>>> 1:
>>>>     jmp *%rax
>>>> END(stub_ptregs_64)
>>>
>>> This'll work, I think, but I still think I prefer keeping as much
>>> complexity as possible in the slow path.  I could be convinced
>>> otherwise, though -- this variant is reasonably clean.
>>
>> On further reflection, there's at least one functional difference.
>> With my variant, modifying pt_regs from sys_foo/ptregs is safe.  In
>> your variant, it's unsafe unless force_iret() is called.  I don't know
>> whether we care.
>
> I can go either way at this point.  My main concern was getting rid of
> the duplicate table.

Agreed.  I'll sleep on it, and maybe someone else has some reason to
prefer one approach over the other.

--Andy



-- 
Andy Lutomirski
AMA Capital Management, LLC
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1287772 — [PATCH] x86/entry/64: Remove duplicate syscall table for fast path

FromAndy Lutomirski <luto@kernel.org>
Date2015-12-09 20:40 +0100
Subject[PATCH] x86/entry/64: Remove duplicate syscall table for fast path
Message-ID<qDSKK-49e-5@gated-at.bofh.it>
In reply to#1287479
Instead of using a duplicate syscall table for the fast path, create
stubs for the syscalls that need pt_regs that dispatch based on the
call site.

I think that this is very likely to introduce a mis-predicted branch
in all such syscalls.  I think that's fine -- all of them are
already very slow.

Heavily based on a patch from Brian Gerst [1].

[1] http://lkml.kernel.org/g/1449666173-15366-1-git-send-email-brgerst@gmail.com

Signed-off-by: Brian Gerst <brgerst@gmail.com>
Cc: the arch/x86 maintainers <x86@kernel.org>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---

Brian, here's a counter-proposal.  It's derived from your patch, but it works
differently.

If people like this, I'll send a new version of the whole series that includes
it at the end.

arch/x86/entry/entry_64.S   | 49 ++++++++++++++++++++++++++++++++++++++-------
 arch/x86/entry/syscall_64.c | 25 +++++------------------
 2 files changed, 47 insertions(+), 27 deletions(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 1ab5362f241d..16779b52419e 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -188,7 +188,15 @@ entry_SYSCALL_64_fastpath:
 #endif
 	ja	1f				/* return -ENOSYS (already in pt_regs->ax) */
 	movq	%r10, %rcx
-	call	*sys_call_table_fastpath_64(, %rax, 8)
+
+	/*
+	 * This call instruction is handled specially in stub_ptregs_64.
+	 * It might end up jumping to the slow path.  If it jumps, rax and
+	 * r11 are clobbered.
+	 */
+	call	*sys_call_table(, %rax, 8)
+.Lentry_SYSCALL_64_after_fastpath_call:
+
 	movq	%rax, RAX(%rsp)
 1:
 
@@ -306,15 +314,42 @@ END(entry_SYSCALL_64)
 
 ENTRY(stub_ptregs_64)
 	/*
-	 * Syscalls marked as needing ptregs that go through the fast path
-	 * land here.  We transfer to the slow path.
+	 * Syscalls marked as needing ptregs land here.
+	 * If we are on the fast path, we need to save the extra regs.
+	 * If we are on the slow path, the extra regs are already saved.
+	 *
+	 * RAX stores a pointer to the C function implementing the syscall.
+	 *
+	 * We can safely clobber RAX (clobbered by return value regardless)
+	 * and R11 (owned by callee and never stores an argument) regardless
+	 * of which path we take.
 	 */
-	DISABLE_INTERRUPTS(CLBR_NONE)
-	TRACE_IRQS_OFF
-	addq	$8, %rsp
-	jmp	entry_SYSCALL64_slow_path
+	leaq	.Lentry_SYSCALL_64_after_fastpath_call(%rip), %r11
+	cmpq	%r11, (%rsp)
+	jne	1f
+
+	/* Called from fast path -- pop return address and jump to slow path */
+	popq	%rax
+	jmp	entry_SYSCALL64_slow_path	/* called from fast path */
+
+1:
+	/* Called from C */
+	jmp	*%rax				/* called from C */
 END(stub_ptregs_64)
 
+.macro ptregs_stub func
+ENTRY(ptregs_\func)
+	leaq	\func(%rip), %rax
+	jmp	stub_ptregs_64
+END(ptregs_\func)
+.endm
+
+/* Instantiate ptregs_stub for each ptregs-using syscall */
+#define __SYSCALL_64_QUAL_(sym)
+#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_stub sym
+#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(sym)
+#include <asm/syscalls_64.h>
+
 /*
  * A newly forked process directly context switches into this address.
  *
diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
index 601745c667ce..9dbc5abb6162 100644
--- a/arch/x86/entry/syscall_64.c
+++ b/arch/x86/entry/syscall_64.c
@@ -6,11 +6,14 @@
 #include <asm/asm-offsets.h>
 #include <asm/syscall.h>
 
-#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
+#define __SYSCALL_64_QUAL_(sym) sym
+#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_##sym
+
+#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long __SYSCALL_64_QUAL_##qual(sym)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 #include <asm/syscalls_64.h>
 #undef __SYSCALL_64
 
-#define __SYSCALL_64(nr, sym, qual) [nr] = sym,
+#define __SYSCALL_64(nr, sym, qual) [nr] = __SYSCALL_64_QUAL_##qual(sym),
 
 extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 
@@ -22,21 +25,3 @@ asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
 	[0 ... __NR_syscall_max] = &sys_ni_syscall,
 #include <asm/syscalls_64.h>
 };
-
-#undef __SYSCALL_64
-
-extern long stub_ptregs_64(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
-
-#define __SYSCALL_64_QUAL_(nr, sym) [nr] = sym,
-#define __SYSCALL_64_QUAL_ptregs(nr, sym) [nr] = stub_ptregs_64,
-
-#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(nr, sym)
-
-asmlinkage const sys_call_ptr_t sys_call_table_fastpath_64[__NR_syscall_max+1] = {
-	/*
-	 * Smells like a compiler bug -- it doesn't work
-	 * when the & below is removed.
-	 */
-	[0 ... __NR_syscall_max] = &sys_ni_syscall,
-#include <asm/syscalls_64.h>
-};
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web