Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1217129 > unrolled thread
| Started by | Andy Lutomirski <luto@kernel.org> |
|---|---|
| First post | 2015-09-02 00:50 +0200 |
| Last post | 2015-09-03 19:20 +0200 |
| Articles | 13 on this page of 33 — 3 participants |
Back to article view | Back to linux.kernel
[RFC 00/30] x86: Rewrite all syscall entries except native 64-bit Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 15/30] x86/entry/64/compat: Set up full pt_regs for all compat syscalls Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 21/30] x86/vdso/compat: Wire up SYSENTER and SYSCSALL for compat userspace Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 26/30] x86/asm: Remove thread_info.sysenter_return Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 27/30] x86/entry: Remove unnecessary IRQ twiddling in fast 32-bit syscalls Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 11/30] x86/vdso/32: Save extra registers in the INT80 vsyscall path Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 25/30] x86/entry/32: Re-implement SYSENTER using the new C path Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 30/30] x86/entry: Micro-optimize compat fast syscall arg fetch Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 14/30] x86/entry/64/compat: Remove most of the fast system call machinery Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 20/30] x86/entry: Add C code for fast system call entries Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 04/30] x86/entry: Move lockdep_sys_exit to prepare_exit_to_usermode Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 13/30] x86/entry/64/compat: Remove audit optimizations Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 06/30] x86/sched/64: Don't save flags on context switch (reinstated) Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 22/30] x86/entry/compat: Implement opportunistic SYSRETL for compat syscalls Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 16/30] x86/entry/syscalls: Move syscall table declarations into asm/syscalls.h Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 18/30] x86/entry: Add do_syscall_32, a C function to do 32-bit syscalls Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 28/30] x86/entry: Make irqs_disabled checks in exit code depend on lockdep Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 19/30] x86/entry/64/compat: Migrate the body of the syscall entry to C Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 23/30] x86/entry/32: Open-code return tracking from fork and kthreads Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 01/30] selftests/x86: Add a test for vDSO unwinding Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 24/30] x86/entry/32: Switch INT80 to the new C syscall path Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
Re: [RFC 24/30] x86/entry/32: Switch INT80 to the new C syscall path Brian Gerst <brgerst@gmail.com> - 2015-09-03 18:50 +0200
Re: [RFC 24/30] x86/entry/32: Switch INT80 to the new C syscall path Andy Lutomirski <luto@amacapital.net> - 2015-09-03 19:30 +0200
[RFC 29/30] x86/entry: Force inlining of 32-bit syscall code Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 17/30] x86/syscalls: Give sys_call_ptr_t a useful type Andy Lutomirski <luto@kernel.org> - 2015-09-02 00:50 +0200
[RFC 03/30] x86/entry/64/compat: Fix SYSENTER's NT flag before user memory access Andy Lutomirski <luto@kernel.org> - 2015-09-02 01:00 +0200
[RFC 05/30] x86/entry/64/compat: After SYSENTER, move STI after the NT fixup Andy Lutomirski <luto@kernel.org> - 2015-09-02 01:00 +0200
[RFC 08/30] x86/asm: Re-add manual CFI infrastructure Andy Lutomirski <luto@kernel.org> - 2015-09-02 01:00 +0200
[RFC 10/30] x86/vdso: Replace hex int80 CFI annotations with gas directives Andy Lutomirski <luto@kernel.org> - 2015-09-02 01:00 +0200
[RFC 02/30] selftests/x86: Add a test for syscall restart and arg modification Andy Lutomirski <luto@kernel.org> - 2015-09-02 01:00 +0200
[RFC 09/30] x86/vdso: Define BUILD_VDSO while building and emit .eh_frame in asm Andy Lutomirski <luto@kernel.org> - 2015-09-02 01:00 +0200
Re: [RFC 00/30] x86: Rewrite all syscall entries except native 64-bit Brian Gerst <brgerst@gmail.com> - 2015-09-03 07:30 +0200
Re: [RFC 00/30] x86: Rewrite all syscall entries except native 64-bit Andy Lutomirski <luto@amacapital.net> - 2015-09-03 19:20 +0200
Page 2 of 2 — ← Prev page 1 [2]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 00:50 +0200 |
| Subject | [RFC 24/30] x86/entry/32: Switch INT80 to the new C syscall path |
| Message-ID | <q42xl-3mq-59@gated-at.bofh.it> |
| In reply to | #1217129 |
Signed-off-by: Andy Lutomirski <luto@kernel.org> --- arch/x86/entry/entry_32.S | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 36b6beb181f6..02881e528945 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -153,13 +153,13 @@ #endif /* CONFIG_X86_32_LAZY_GS */ -.macro SAVE_ALL +.macro SAVE_ALL pt_regs_ax=%eax cld PUSH_GS pushl %fs pushl %es pushl %ds - pushl %eax + pushl \pt_regs_ax pushl %ebp pushl %edi pushl %esi @@ -370,20 +370,17 @@ ENDPROC(entry_SYSENTER_32) # system call handler stub ENTRY(entry_INT80_32) ASM_CLAC - pushl %eax # save orig_eax - SAVE_ALL - GET_THREAD_INFO(%ebp) - # system call tracing in operation / emulation - testl $_TIF_WORK_SYSCALL_ENTRY, TI_flags(%ebp) - jnz syscall_trace_entry - cmpl $(NR_syscalls), %eax - jae syscall_badsys -syscall_call: - call *sys_call_table(, %eax, 4) -syscall_after_call: - movl %eax, PT_EAX(%esp) # store the return value -syscall_exit: - jmp syscall_exit_work + pushl %eax /* pt_regs->orig_ax */ + SAVE_ALL pt_regs_ax=$-ENOSYS /* save rest, load -ENOSYS into ax */ + + /* + * User mode is traced as though IRQs are on, and the interrupt gate + * turned them off. + */ + TRACE_IRQS_OFF + + movl %esp, %eax + call do_int80_syscall_32 restore_all: TRACE_IRQS_IRET @@ -491,11 +488,6 @@ syscall_fault: jmp resume_userspace END(syscall_fault) -syscall_badsys: - movl $-ENOSYS, %eax - jmp syscall_after_call -END(syscall_badsys) - sysenter_badsys: movl $-ENOSYS, %eax jmp sysenter_after_call -- 2.4.3 -- 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]
| From | Brian Gerst <brgerst@gmail.com> |
|---|---|
| Date | 2015-09-03 18:50 +0200 |
| Subject | Re: [RFC 24/30] x86/entry/32: Switch INT80 to the new C syscall path |
| Message-ID | <q4FS2-M8-17@gated-at.bofh.it> |
| In reply to | #1217152 |
On Tue, Sep 1, 2015 at 6:41 PM, Andy Lutomirski <luto@kernel.org> wrote: > Signed-off-by: Andy Lutomirski <luto@kernel.org> > --- > arch/x86/entry/entry_32.S | 34 +++++++++++++--------------------- > 1 file changed, 13 insertions(+), 21 deletions(-) > > diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S > index 36b6beb181f6..02881e528945 100644 > --- a/arch/x86/entry/entry_32.S > +++ b/arch/x86/entry/entry_32.S > @@ -153,13 +153,13 @@ > > #endif /* CONFIG_X86_32_LAZY_GS */ > > -.macro SAVE_ALL > +.macro SAVE_ALL pt_regs_ax=%eax > cld > PUSH_GS > pushl %fs > pushl %es > pushl %ds > - pushl %eax > + pushl \pt_regs_ax > pushl %ebp > pushl %edi > pushl %esi > @@ -370,20 +370,17 @@ ENDPROC(entry_SYSENTER_32) > # system call handler stub > ENTRY(entry_INT80_32) > ASM_CLAC > - pushl %eax # save orig_eax > - SAVE_ALL > - GET_THREAD_INFO(%ebp) > - # system call tracing in operation / emulation > - testl $_TIF_WORK_SYSCALL_ENTRY, TI_flags(%ebp) > - jnz syscall_trace_entry > - cmpl $(NR_syscalls), %eax > - jae syscall_badsys > -syscall_call: > - call *sys_call_table(, %eax, 4) > -syscall_after_call: > - movl %eax, PT_EAX(%esp) # store the return value > -syscall_exit: > - jmp syscall_exit_work > + pushl %eax /* pt_regs->orig_ax */ > + SAVE_ALL pt_regs_ax=$-ENOSYS /* save rest, load -ENOSYS into ax */ > + > + /* > + * User mode is traced as though IRQs are on, and the interrupt gate > + * turned them off. > + */ > + TRACE_IRQS_OFF > + > + movl %esp, %eax > + call do_int80_syscall_32 > > restore_all: > TRACE_IRQS_IRET > @@ -491,11 +488,6 @@ syscall_fault: > jmp resume_userspace > END(syscall_fault) > > -syscall_badsys: > - movl $-ENOSYS, %eax > - jmp syscall_after_call > -END(syscall_badsys) > - > sysenter_badsys: > movl $-ENOSYS, %eax > jmp sysenter_after_call > -- > 2.4.3 > While bisecting a boot failure on the 32-bit native kernel I came across this build error: arch/x86/built-in.o: In function `syscall_trace_entry': /home/bgerst/kernel/linux/arch/x86/entry/entry_32.S:468: undefined reference to `syscall_call' /home/bgerst/kernel/linux/arch/x86/entry/entry_32.S:469: undefined reference to `syscall_exit' -- 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]
| From | Andy Lutomirski <luto@amacapital.net> |
|---|---|
| Date | 2015-09-03 19:30 +0200 |
| Subject | Re: [RFC 24/30] x86/entry/32: Switch INT80 to the new C syscall path |
| Message-ID | <q4GuM-1LD-59@gated-at.bofh.it> |
| In reply to | #1218437 |
On Thu, Sep 3, 2015 at 9:45 AM, Brian Gerst <brgerst@gmail.com> wrote: > On Tue, Sep 1, 2015 at 6:41 PM, Andy Lutomirski <luto@kernel.org> wrote: >> Signed-off-by: Andy Lutomirski <luto@kernel.org> >> --- >> arch/x86/entry/entry_32.S | 34 +++++++++++++--------------------- >> 1 file changed, 13 insertions(+), 21 deletions(-) >> >> diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S >> index 36b6beb181f6..02881e528945 100644 >> --- a/arch/x86/entry/entry_32.S >> +++ b/arch/x86/entry/entry_32.S >> @@ -153,13 +153,13 @@ >> >> #endif /* CONFIG_X86_32_LAZY_GS */ >> >> -.macro SAVE_ALL >> +.macro SAVE_ALL pt_regs_ax=%eax >> cld >> PUSH_GS >> pushl %fs >> pushl %es >> pushl %ds >> - pushl %eax >> + pushl \pt_regs_ax >> pushl %ebp >> pushl %edi >> pushl %esi >> @@ -370,20 +370,17 @@ ENDPROC(entry_SYSENTER_32) >> # system call handler stub >> ENTRY(entry_INT80_32) >> ASM_CLAC >> - pushl %eax # save orig_eax >> - SAVE_ALL >> - GET_THREAD_INFO(%ebp) >> - # system call tracing in operation / emulation >> - testl $_TIF_WORK_SYSCALL_ENTRY, TI_flags(%ebp) >> - jnz syscall_trace_entry >> - cmpl $(NR_syscalls), %eax >> - jae syscall_badsys >> -syscall_call: >> - call *sys_call_table(, %eax, 4) >> -syscall_after_call: >> - movl %eax, PT_EAX(%esp) # store the return value >> -syscall_exit: >> - jmp syscall_exit_work >> + pushl %eax /* pt_regs->orig_ax */ >> + SAVE_ALL pt_regs_ax=$-ENOSYS /* save rest, load -ENOSYS into ax */ >> + >> + /* >> + * User mode is traced as though IRQs are on, and the interrupt gate >> + * turned them off. >> + */ >> + TRACE_IRQS_OFF >> + >> + movl %esp, %eax >> + call do_int80_syscall_32 >> >> restore_all: >> TRACE_IRQS_IRET >> @@ -491,11 +488,6 @@ syscall_fault: >> jmp resume_userspace >> END(syscall_fault) >> >> -syscall_badsys: >> - movl $-ENOSYS, %eax >> - jmp syscall_after_call >> -END(syscall_badsys) >> - >> sysenter_badsys: >> movl $-ENOSYS, %eax >> jmp sysenter_after_call >> -- >> 2.4.3 >> > > While bisecting a boot failure on the 32-bit native kernel I came > across this build error: > arch/x86/built-in.o: In function `syscall_trace_entry': > /home/bgerst/kernel/linux/arch/x86/entry/entry_32.S:468: undefined > reference to `syscall_call' > /home/bgerst/kernel/linux/arch/x86/entry/entry_32.S:469: undefined > reference to `syscall_exit' > Whoops! I'll fix that up for v2. --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]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 00:50 +0200 |
| Subject | [RFC 29/30] x86/entry: Force inlining of 32-bit syscall code |
| Message-ID | <q42xl-3mq-61@gated-at.bofh.it> |
| In reply to | #1217129 |
On systems that support fast syscalls, we only really care about the
performance of the fast syscall path. Forcibly inline it and add
a likely annotation.
This saves 4-6 cycles.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
arch/x86/entry/common.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 0fa55f0736f6..a3c4e7aa573b 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -324,9 +324,11 @@ __visible void syscall_return_slowpath(struct pt_regs *regs)
#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
/*
* Does a 32-bit syscall. Called with IRQs on and does all entry and
- * exit work and returns with IRQs off.
+ * exit work and returns with IRQs off. This function is extremely hot
+ * in workloads that use it, and it's usually called from
+ * do_fast_syscall_32, so forcibly inline it to improve performance.
*/
-static void do_syscall_32_irqs_on(struct pt_regs *regs)
+static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
{
struct thread_info *ti = pt_regs_to_thread_info(regs);
unsigned int nr = (unsigned int)regs->orig_ax;
@@ -345,7 +347,7 @@ static void do_syscall_32_irqs_on(struct pt_regs *regs)
nr = syscall_trace_enter(regs);
}
- if (nr < IA32_NR_syscalls) {
+ if (likely(nr < IA32_NR_syscalls)) {
/*
* It's possible that a 32-bit syscall implementation
* takes a 64-bit parameter but nonetheless assumes that
--
2.4.3
--
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]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 00:50 +0200 |
| Subject | [RFC 17/30] x86/syscalls: Give sys_call_ptr_t a useful type |
| Message-ID | <q42xl-3mq-57@gated-at.bofh.it> |
| In reply to | #1217129 |
Syscalls are asmlinkage functions (on 32-bit kernels), take six args
of type unsigned long, and return long. Note that uml could
probably be slightly cleaned up on top of this patch.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
arch/x86/entry/syscall_32.c | 4 ++--
arch/x86/entry/syscall_64.c | 4 ++--
arch/x86/include/asm/syscall.h | 4 +++-
arch/x86/um/sys_call_table_32.c | 4 ++--
arch/x86/um/sys_call_table_64.c | 4 ++--
5 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c
index 429460d7721e..9a6649857106 100644
--- a/arch/x86/entry/syscall_32.c
+++ b/arch/x86/entry/syscall_32.c
@@ -12,13 +12,13 @@
#define SYM(sym, compat) sym
#endif
-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void SYM(sym, compat)(void) ;
+#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage long SYM(sym, compat)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
#include <asm/syscalls_32.h>
#undef __SYSCALL_I386
#define __SYSCALL_I386(nr, sym, compat) [nr] = SYM(sym, compat),
-extern asmlinkage void sys_ni_syscall(void);
+extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
__visible const sys_call_ptr_t ia32_sys_call_table[__NR_syscall_compat_max+1] = {
/*
diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
index 4ac730b37f0b..41283d22be7a 100644
--- a/arch/x86/entry/syscall_64.c
+++ b/arch/x86/entry/syscall_64.c
@@ -14,13 +14,13 @@
# define __SYSCALL_X32(nr, sym, compat) /* nothing */
#endif
-#define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ;
+#define __SYSCALL_64(nr, sym, compat) extern asmlinkage long 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, compat) [nr] = sym,
-extern void sys_ni_syscall(void);
+extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
/*
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
index f3ff2ef36e19..999b7cd2e78c 100644
--- a/arch/x86/include/asm/syscall.h
+++ b/arch/x86/include/asm/syscall.h
@@ -20,7 +20,9 @@
#include <asm/thread_info.h> /* for TS_COMPAT */
#include <asm/unistd.h>
-typedef asmlinkage void (*sys_call_ptr_t)(void);
+typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long);
extern const sys_call_ptr_t sys_call_table[];
#if defined(CONFIG_X86_32)
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
index d738e9c96036..439c0994b696 100644
--- a/arch/x86/um/sys_call_table_32.c
+++ b/arch/x86/um/sys_call_table_32.c
@@ -25,13 +25,13 @@
#define old_mmap sys_old_mmap
-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ;
+#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
#include <asm/syscalls_32.h>
#undef __SYSCALL_I386
#define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym,
-extern asmlinkage void sys_ni_syscall(void);
+extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
/*
diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c
index 1ff9a21b2645..b74ea6c2c0e7 100644
--- a/arch/x86/um/sys_call_table_64.c
+++ b/arch/x86/um/sys_call_table_64.c
@@ -38,13 +38,13 @@
#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
#define __SYSCALL_X32(nr, sym, compat) /* Not supported */
-#define __SYSCALL_64(nr, sym, compat) extern asmlinkage void sym(void) ;
+#define __SYSCALL_64(nr, sym, compat) extern asmlinkage long 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, compat) [ nr ] = sym,
-extern void sys_ni_syscall(void);
+extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
const sys_call_ptr_t sys_call_table[] ____cacheline_aligned = {
/*
--
2.4.3
--
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]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 01:00 +0200 |
| Subject | [RFC 03/30] x86/entry/64/compat: Fix SYSENTER's NT flag before user memory access |
| Message-ID | <q42GZ-3xO-1@gated-at.bofh.it> |
| In reply to | #1217129 |
Clearing NT is part of the prologue, whereas loading up arg6 makes more sense to think about as part of syscall processing. Reorder them. Signed-off-by: Andy Lutomirski <luto@kernel.org> --- arch/x86/entry/entry_64_compat.S | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S index a9360d40fb7f..aa76864a8a6b 100644 --- a/arch/x86/entry/entry_64_compat.S +++ b/arch/x86/entry/entry_64_compat.S @@ -89,15 +89,6 @@ ENTRY(entry_SYSENTER_compat) sub $(10*8), %rsp /* pt_regs->r8-11, bp, bx, r12-15 not saved */ /* - * no need to do an access_ok check here because rbp has been - * 32-bit zero extended - */ - ASM_STAC -1: movl (%rbp), %ebp - _ASM_EXTABLE(1b, ia32_badarg) - ASM_CLAC - - /* * Sysenter doesn't filter flags, so we need to clear NT * ourselves. To save a few cycles, we can check whether * NT was set instead of doing an unconditional popfq. @@ -106,6 +97,15 @@ ENTRY(entry_SYSENTER_compat) jnz sysenter_fix_flags sysenter_flags_fixed: + /* + * no need to do an access_ok check here because rbp has been + * 32-bit zero extended + */ + ASM_STAC +1: movl (%rbp), %ebp + _ASM_EXTABLE(1b, ia32_badarg) + ASM_CLAC + orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS) testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) jnz sysenter_tracesys -- 2.4.3 -- 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]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 01:00 +0200 |
| Subject | [RFC 05/30] x86/entry/64/compat: After SYSENTER, move STI after the NT fixup |
| Message-ID | <q42GZ-3xO-5@gated-at.bofh.it> |
| In reply to | #1217129 |
We eventually want to make it all the way into C code before enabling interrupts. We need to rework our flags handling slightly to delay enabling interrupts. Signed-off-by: Andy Lutomirski <luto@kernel.org> --- arch/x86/entry/entry_64_compat.S | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S index aa76864a8a6b..1432d60a1f4a 100644 --- a/arch/x86/entry/entry_64_compat.S +++ b/arch/x86/entry/entry_64_compat.S @@ -58,14 +58,9 @@ ENDPROC(native_usergs_sysret32) * with the int 0x80 path. */ ENTRY(entry_SYSENTER_compat) - /* - * Interrupts are off on entry. - * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON, - * it is too small to ever cause noticeable irq latency. - */ + /* Interrupts are off on entry. */ SWAPGS_UNSAFE_STACK movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp - ENABLE_INTERRUPTS(CLBR_NONE) /* Zero-extending 32-bit regs, do not remove */ movl %ebp, %ebp @@ -76,7 +71,16 @@ ENTRY(entry_SYSENTER_compat) /* Construct struct pt_regs on stack */ pushq $__USER32_DS /* pt_regs->ss */ pushq %rbp /* pt_regs->sp */ - pushfq /* pt_regs->flags */ + + /* + * Push flags. This is nasty. First, interrupts are currently + * off, but we need pt_regs->flags to have IF set. Second, even + * if TF was set when SYSENTER started, it's clear by now. We fix + * that later using TIF_SINGLESTEP. + */ + pushfq /* pt_regs->flags (except IF = 0) */ + orl $X86_EFLAGS_IF, (%rsp) /* Fix saved flags */ + pushq $__USER32_CS /* pt_regs->cs */ pushq %r10 /* pt_regs->ip = thread_info->sysenter_return */ pushq %rax /* pt_regs->orig_ax */ @@ -92,12 +96,22 @@ ENTRY(entry_SYSENTER_compat) * Sysenter doesn't filter flags, so we need to clear NT * ourselves. To save a few cycles, we can check whether * NT was set instead of doing an unconditional popfq. + * This needs to happen before enabling interrupts so that + * we don't get preempted with NT set. */ testl $X86_EFLAGS_NT, EFLAGS(%rsp) jnz sysenter_fix_flags sysenter_flags_fixed: /* + * Re-enable interrupts. IRQ tracing already thinks that IRQs are + * on (since we treat user mode as having IRQs on), and the + * prologue above is too short for it to be worth adding a + * tracing round trip. + */ + ENABLE_INTERRUPTS(CLBR_NONE) + + /* * no need to do an access_ok check here because rbp has been * 32-bit zero extended */ @@ -244,7 +258,7 @@ sysexit_audit: #endif sysenter_fix_flags: - pushq $(X86_EFLAGS_IF|X86_EFLAGS_FIXED) + pushq $X86_EFLAGS_FIXED popfq jmp sysenter_flags_fixed -- 2.4.3 -- 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]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 01:00 +0200 |
| Subject | [RFC 08/30] x86/asm: Re-add manual CFI infrastructure |
| Message-ID | <q42H0-3xO-17@gated-at.bofh.it> |
| In reply to | #1217129 |
Commit 131484c8da97 ("x86/debug: Remove perpetually broken,
unmaintainable dwarf annotations") removed all the manual DWARF
annotations outside the vDSO. It also removed the macros we used
for the manual annotations.
Re-add the macros so that we can clean up the vDSO annotations.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
arch/x86/Makefile | 10 ++-
arch/x86/include/asm/dwarf2.h | 170 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 178 insertions(+), 2 deletions(-)
create mode 100644 arch/x86/include/asm/dwarf2.h
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 054ff969fcdb..e4a537ed5350 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -159,6 +159,12 @@ endif
sp-$(CONFIG_X86_32) := esp
sp-$(CONFIG_X86_64) := rsp
+# do binutils support CFI?
+cfi := $(call as-instr,.cfi_startproc\n.cfi_rel_offset $(sp-y)$(comma)0\n.cfi_endproc,-DCONFIG_AS_CFI=1)
+# is .cfi_signal_frame supported too?
+cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1)
+cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTIONS=1)
+
# does binutils support specific instructions?
asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
asinstr += $(call as-instr,pshufb %xmm0$(comma)%xmm0,-DCONFIG_AS_SSSE3=1)
@@ -166,8 +172,8 @@ asinstr += $(call as-instr,crc32l %eax$(comma)%eax,-DCONFIG_AS_CRC32=1)
avx_instr := $(call as-instr,vxorps %ymm0$(comma)%ymm1$(comma)%ymm2,-DCONFIG_AS_AVX=1)
avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
-KBUILD_AFLAGS += $(asinstr) $(avx_instr) $(avx2_instr)
-KBUILD_CFLAGS += $(asinstr) $(avx_instr) $(avx2_instr)
+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr)
+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr)
LDFLAGS := -m elf_$(UTS_MACHINE)
diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
new file mode 100644
index 000000000000..de1cdaf4d743
--- /dev/null
+++ b/arch/x86/include/asm/dwarf2.h
@@ -0,0 +1,170 @@
+#ifndef _ASM_X86_DWARF2_H
+#define _ASM_X86_DWARF2_H
+
+#ifndef __ASSEMBLY__
+#warning "asm/dwarf2.h should be only included in pure assembly files"
+#endif
+
+/*
+ * Macros for dwarf2 CFI unwind table entries.
+ * See "as.info" for details on these pseudo ops. Unfortunately
+ * they are only supported in very new binutils, so define them
+ * away for older version.
+ */
+
+#ifdef CONFIG_AS_CFI
+
+#define CFI_STARTPROC .cfi_startproc
+#define CFI_ENDPROC .cfi_endproc
+#define CFI_DEF_CFA .cfi_def_cfa
+#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register
+#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset
+#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset
+#define CFI_OFFSET .cfi_offset
+#define CFI_REL_OFFSET .cfi_rel_offset
+#define CFI_REGISTER .cfi_register
+#define CFI_RESTORE .cfi_restore
+#define CFI_REMEMBER_STATE .cfi_remember_state
+#define CFI_RESTORE_STATE .cfi_restore_state
+#define CFI_UNDEFINED .cfi_undefined
+#define CFI_ESCAPE .cfi_escape
+
+#ifdef CONFIG_AS_CFI_SIGNAL_FRAME
+#define CFI_SIGNAL_FRAME .cfi_signal_frame
+#else
+#define CFI_SIGNAL_FRAME
+#endif
+
+#if defined(CONFIG_AS_CFI_SECTIONS) && defined(__ASSEMBLY__)
+ /*
+ * Emit CFI data in .debug_frame sections, not .eh_frame sections.
+ * The latter we currently just discard since we don't do DWARF
+ * unwinding at runtime. So only the offline DWARF information is
+ * useful to anyone. Note we should not use this directive if this
+ * file is used in the vDSO assembly, or if vmlinux.lds.S gets
+ * changed so it doesn't discard .eh_frame.
+ */
+ .cfi_sections .debug_frame
+#endif
+
+#else
+
+/*
+ * Due to the structure of pre-exisiting code, don't use assembler line
+ * comment character # to ignore the arguments. Instead, use a dummy macro.
+ */
+.macro cfi_ignore a=0, b=0, c=0, d=0
+.endm
+
+#define CFI_STARTPROC cfi_ignore
+#define CFI_ENDPROC cfi_ignore
+#define CFI_DEF_CFA cfi_ignore
+#define CFI_DEF_CFA_REGISTER cfi_ignore
+#define CFI_DEF_CFA_OFFSET cfi_ignore
+#define CFI_ADJUST_CFA_OFFSET cfi_ignore
+#define CFI_OFFSET cfi_ignore
+#define CFI_REL_OFFSET cfi_ignore
+#define CFI_REGISTER cfi_ignore
+#define CFI_RESTORE cfi_ignore
+#define CFI_REMEMBER_STATE cfi_ignore
+#define CFI_RESTORE_STATE cfi_ignore
+#define CFI_UNDEFINED cfi_ignore
+#define CFI_ESCAPE cfi_ignore
+#define CFI_SIGNAL_FRAME cfi_ignore
+
+#endif
+
+/*
+ * An attempt to make CFI annotations more or less
+ * correct and shorter. It is implied that you know
+ * what you're doing if you use them.
+ */
+#ifdef __ASSEMBLY__
+#ifdef CONFIG_X86_64
+ .macro pushq_cfi reg
+ pushq \reg
+ CFI_ADJUST_CFA_OFFSET 8
+ .endm
+
+ .macro pushq_cfi_reg reg
+ pushq %\reg
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET \reg, 0
+ .endm
+
+ .macro popq_cfi reg
+ popq \reg
+ CFI_ADJUST_CFA_OFFSET -8
+ .endm
+
+ .macro popq_cfi_reg reg
+ popq %\reg
+ CFI_ADJUST_CFA_OFFSET -8
+ CFI_RESTORE \reg
+ .endm
+
+ .macro pushfq_cfi
+ pushfq
+ CFI_ADJUST_CFA_OFFSET 8
+ .endm
+
+ .macro popfq_cfi
+ popfq
+ CFI_ADJUST_CFA_OFFSET -8
+ .endm
+
+ .macro movq_cfi reg offset=0
+ movq %\reg, \offset(%rsp)
+ CFI_REL_OFFSET \reg, \offset
+ .endm
+
+ .macro movq_cfi_restore offset reg
+ movq \offset(%rsp), %\reg
+ CFI_RESTORE \reg
+ .endm
+#else /*!CONFIG_X86_64*/
+ .macro pushl_cfi reg
+ pushl \reg
+ CFI_ADJUST_CFA_OFFSET 4
+ .endm
+
+ .macro pushl_cfi_reg reg
+ pushl %\reg
+ CFI_ADJUST_CFA_OFFSET 4
+ CFI_REL_OFFSET \reg, 0
+ .endm
+
+ .macro popl_cfi reg
+ popl \reg
+ CFI_ADJUST_CFA_OFFSET -4
+ .endm
+
+ .macro popl_cfi_reg reg
+ popl %\reg
+ CFI_ADJUST_CFA_OFFSET -4
+ CFI_RESTORE \reg
+ .endm
+
+ .macro pushfl_cfi
+ pushfl
+ CFI_ADJUST_CFA_OFFSET 4
+ .endm
+
+ .macro popfl_cfi
+ popfl
+ CFI_ADJUST_CFA_OFFSET -4
+ .endm
+
+ .macro movl_cfi reg offset=0
+ movl %\reg, \offset(%esp)
+ CFI_REL_OFFSET \reg, \offset
+ .endm
+
+ .macro movl_cfi_restore offset reg
+ movl \offset(%esp), %\reg
+ CFI_RESTORE \reg
+ .endm
+#endif /*!CONFIG_X86_64*/
+#endif /*__ASSEMBLY__*/
+
+#endif /* _ASM_X86_DWARF2_H */
--
2.4.3
--
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]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 01:00 +0200 |
| Subject | [RFC 10/30] x86/vdso: Replace hex int80 CFI annotations with gas directives |
| Message-ID | <q42H0-3xO-19@gated-at.bofh.it> |
| In reply to | #1217129 |
Maintaining the current CFI annotations written in R'lyehian is difficult for most of us. Translate them to something a little closer to English. This will remove the CFI data for kernels built with extremely old versions of binutils. I think this is a fair tradeoff for the ability for mortals to edit the asm. Signed-off-by: Andy Lutomirski <luto@kernel.org> --- arch/x86/entry/vdso/vdso32/system_call.S | 48 ++++++-------------------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/arch/x86/entry/vdso/vdso32/system_call.S b/arch/x86/entry/vdso/vdso32/system_call.S index b15b7c01aedb..b52cbfbe119e 100644 --- a/arch/x86/entry/vdso/vdso32/system_call.S +++ b/arch/x86/entry/vdso/vdso32/system_call.S @@ -1,6 +1,10 @@ /* * Code for the vDSO. This version uses the old int $0x80 method. - * +*/ + +#include <asm/dwarf2.h> + +/* * First get the common code for the sigreturn entry points. * This must come first. */ @@ -11,46 +15,10 @@ .type __kernel_vsyscall,@function ALIGN __kernel_vsyscall: -.LSTART_vsyscall: + CFI_STARTPROC int $0x80 ret -.LEND_vsyscall: - .size __kernel_vsyscall,.-.LSTART_vsyscall - .previous - - .section .eh_frame,"a",@progbits -.LSTARTFRAMEDLSI: - .long .LENDCIEDLSI-.LSTARTCIEDLSI -.LSTARTCIEDLSI: - .long 0 /* CIE ID */ - .byte 1 /* Version number */ - .string "zR" /* NUL-terminated augmentation string */ - .uleb128 1 /* Code alignment factor */ - .sleb128 -4 /* Data alignment factor */ - .byte 8 /* Return address register column */ - .uleb128 1 /* Augmentation value length */ - .byte 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */ - .byte 0x0c /* DW_CFA_def_cfa */ - .uleb128 4 - .uleb128 4 - .byte 0x88 /* DW_CFA_offset, column 0x8 */ - .uleb128 1 - .align 4 -.LENDCIEDLSI: - .long .LENDFDEDLSI-.LSTARTFDEDLSI /* Length FDE */ -.LSTARTFDEDLSI: - .long .LSTARTFDEDLSI-.LSTARTFRAMEDLSI /* CIE pointer */ - .long .LSTART_vsyscall-. /* PC-relative start address */ - .long .LEND_vsyscall-.LSTART_vsyscall - .uleb128 0 - .align 4 -.LENDFDEDLSI: - .previous + CFI_ENDPROC - /* - * Pad out the segment to match the size of the sysenter.S version. - */ -VDSO32_vsyscall_eh_frame_size = 0x40 - .section .data,"aw",@progbits - .space VDSO32_vsyscall_eh_frame_size-(.LENDFDEDLSI-.LSTARTFRAMEDLSI), 0 + .size __kernel_vsyscall,.-__kernel_vsyscall .previous -- 2.4.3 -- 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]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 01:00 +0200 |
| Subject | [RFC 02/30] selftests/x86: Add a test for syscall restart and arg modification |
| Message-ID | <q42H0-3xO-27@gated-at.bofh.it> |
| In reply to | #1217129 |
This tests assumptions about how fast syscall works wrt pt_regs and,
in particular, what happens if IP is decremented by 2 during a syscall.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
tools/testing/selftests/x86/Makefile | 3 +-
tools/testing/selftests/x86/ptrace_syscall.c | 294 +++++++++++++++++++++
.../testing/selftests/x86/raw_syscall_helper_32.S | 46 ++++
3 files changed, 342 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/x86/ptrace_syscall.c
create mode 100644 tools/testing/selftests/x86/raw_syscall_helper_32.S
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index 751d3e040dff..d4a1fa755fc5 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -4,7 +4,7 @@ include ../lib.mk
.PHONY: all all_32 all_64 warn_32bit_failure clean
-TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt
+TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt ptrace_syscall
TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn unwind_vdso
TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
@@ -60,3 +60,4 @@ endif
# Some tests have additional dependencies.
sysret_ss_attrs_64: thunks.S
+ptrace_syscall_32: raw_syscall_helper_32.S
diff --git a/tools/testing/selftests/x86/ptrace_syscall.c b/tools/testing/selftests/x86/ptrace_syscall.c
new file mode 100644
index 000000000000..5105b49cd8aa
--- /dev/null
+++ b/tools/testing/selftests/x86/ptrace_syscall.c
@@ -0,0 +1,294 @@
+#define _GNU_SOURCE
+
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include <sys/user.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include <asm/ptrace-abi.h>
+#include <sys/auxv.h>
+
+/* Bitness-agnostic defines for user_regs_struct fields. */
+#ifdef __x86_64__
+# define user_syscall_nr orig_rax
+# define user_arg0 rdi
+# define user_arg1 rsi
+# define user_arg2 rdx
+# define user_arg3 r10
+# define user_arg4 r8
+# define user_arg5 r9
+# define user_ip rip
+# define user_ax rax
+#else
+# define user_syscall_nr orig_eax
+# define user_arg0 ebx
+# define user_arg1 ecx
+# define user_arg2 edx
+# define user_arg3 esi
+# define user_arg4 edi
+# define user_arg5 ebp
+# define user_ip eip
+# define user_ax eax
+#endif
+
+static int nerrs = 0;
+
+struct syscall_args32 {
+ uint32_t nr, arg0, arg1, arg2, arg3, arg4, arg5;
+};
+
+#ifdef __i386__
+extern void sys32_helper(struct syscall_args32 *, void *);
+extern void int80_and_ret(void);
+#endif
+
+/*
+ * Helper to invoke int80 with controlled regs and capture the final regs.
+ */
+static void do_full_int80(struct syscall_args32 *args)
+{
+#ifdef __x86_64__
+ register unsigned long bp asm("bp") = args->arg5;
+ asm volatile ("int $0x80"
+ : "+a" (args->nr),
+ "+b" (args->arg0), "+c" (args->arg1), "+d" (args->arg2),
+ "+S" (args->arg3), "+D" (args->arg4), "+r" (bp));
+ args->arg5 = bp;
+#else
+ sys32_helper(args, int80_and_ret);
+#endif
+}
+
+#ifdef __i386__
+static void (*vsyscall32)(void);
+
+/*
+ * Nasty helper to invoke AT_SYSINFO (i.e. __kernel_vsyscall) with
+ * controlled regs and capture the final regs. This is so nasty that it
+ * crashes my copy of gdb :)
+ */
+static void do_full_vsyscall32(struct syscall_args32 *args)
+{
+ sys32_helper(args, vsyscall32);
+}
+#endif
+
+static siginfo_t wait_trap(pid_t chld)
+{
+ siginfo_t si;
+ if (waitid(P_PID, chld, &si, WEXITED|WSTOPPED) != 0)
+ err(1, "waitid");
+ if (si.si_pid != chld)
+ errx(1, "got unexpected pid in event\n");
+ if (si.si_code != CLD_TRAPPED)
+ errx(1, "got unexpected event type %d\n", si.si_code);
+ return si;
+}
+
+static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
+ int flags)
+{
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_sigaction = handler;
+ sa.sa_flags = SA_SIGINFO | flags;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(sig, &sa, 0))
+ err(1, "sigaction");
+}
+
+static void clearhandler(int sig)
+{
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(sig, &sa, 0))
+ err(1, "sigaction");
+}
+
+#ifdef __x86_64__
+# define REG_BP REG_RBP
+#else
+# define REG_BP REG_EBP
+#endif
+
+static void empty_handler(int sig, siginfo_t *si, void *ctx_void)
+{
+}
+
+static void test_sys32_regs(void (*do_syscall)(struct syscall_args32 *))
+{
+ struct syscall_args32 args = {
+ .nr = 224, /* gettid */
+ .arg0 = 10, .arg1 = 11, .arg2 = 12,
+ .arg3 = 13, .arg4 = 14, .arg5 = 15,
+ };
+
+ do_syscall(&args);
+
+ if (args.nr != getpid() ||
+ args.arg0 != 10 || args.arg1 != 11 || args.arg2 != 12 ||
+ args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) {
+ printf("[FAIL]\tgetpid() failed to preseve regs\n");
+ nerrs++;
+ } else {
+ printf("[OK]\tgetpid() preserves regs\n");
+ }
+
+ sethandler(SIGUSR1, empty_handler, 0);
+
+ args.nr = 37; /* kill */
+ args.arg0 = getpid();
+ args.arg1 = SIGUSR1;
+ do_syscall(&args);
+ if (args.nr != 0 ||
+ args.arg0 != getpid() || args.arg1 != SIGUSR1 || args.arg2 != 12 ||
+ args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) {
+ printf("[FAIL]\tkill(getpid(), SIGUSR1) failed to preseve regs\n");
+ nerrs++;
+ } else {
+ printf("[OK]\tkill(getpid(), SIGUSR1) preserves regs\n");
+ }
+ clearhandler(SIGUSR1);
+}
+
+static void test_ptrace_syscall_restart(void)
+{
+ printf("[RUN]\tptrace-induced syscall restart\n");
+ pid_t chld = fork();
+ if (chld < 0)
+ err(1, "fork");
+
+ if (chld == 0) {
+ if (ptrace(PTRACE_TRACEME, 0, 0, 0) != 0)
+ err(1, "PTRACE_TRACEME");
+
+ printf("\tChild will make one syscall\n");
+ raise(SIGSTOP);
+
+ syscall(SYS_gettid, 10, 11, 12, 13, 14, 15);
+ _exit(0);
+ }
+
+ int status;
+
+ /* Wait for SIGSTOP. */
+ if (waitpid(chld, &status, 0) != chld || !WIFSTOPPED(status))
+ err(1, "waitpid");
+
+ struct user_regs_struct regs;
+
+ printf("[RUN]\tSYSEMU\n");
+ if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
+ err(1, "PTRACE_SYSCALL");
+ wait_trap(chld);
+
+ if (ptrace(PTRACE_GETREGS, chld, 0, ®s) != 0)
+ err(1, "PTRACE_GETREGS");
+
+ if (regs.user_syscall_nr != SYS_gettid ||
+ regs.user_arg0 != 10 || regs.user_arg1 != 11 ||
+ regs.user_arg2 != 12 || regs.user_arg3 != 13 ||
+ regs.user_arg4 != 14 || regs.user_arg5 != 15) {
+ printf("[FAIL]\tInitial args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", (unsigned long)regs.user_syscall_nr, (unsigned long)regs.user_arg0, (unsigned long)regs.user_arg1, (unsigned long)regs.user_arg2, (unsigned long)regs.user_arg3, (unsigned long)regs.user_arg4, (unsigned long)regs.user_arg5);
+ nerrs++;
+ } else {
+ printf("[OK]\tInitial nr and args are correct\n");
+ }
+
+ printf("[RUN]\tRestart the syscall (ip = 0x%lx)\n",
+ (unsigned long)regs.user_ip);
+
+ /*
+ * This does exactly what it appears to do if syscall is int80 or
+ * SYSCALL64. For SYSCALL32 or SYSENTER, though, this is highly
+ * magical. It needs to work so that ptrace and syscall restart
+ * work as expected.
+ */
+ regs.user_ax = regs.user_syscall_nr;
+ regs.user_ip -= 2;
+ if (ptrace(PTRACE_SETREGS, chld, 0, ®s) != 0)
+ err(1, "PTRACE_SETREGS");
+
+ if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
+ err(1, "PTRACE_SYSCALL");
+ wait_trap(chld);
+
+ if (ptrace(PTRACE_GETREGS, chld, 0, ®s) != 0)
+ err(1, "PTRACE_GETREGS");
+
+ if (regs.user_syscall_nr != SYS_gettid ||
+ regs.user_arg0 != 10 || regs.user_arg1 != 11 ||
+ regs.user_arg2 != 12 || regs.user_arg3 != 13 ||
+ regs.user_arg4 != 14 || regs.user_arg5 != 15) {
+ printf("[FAIL]\tRestart nr or args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", (unsigned long)regs.user_syscall_nr, (unsigned long)regs.user_arg0, (unsigned long)regs.user_arg1, (unsigned long)regs.user_arg2, (unsigned long)regs.user_arg3, (unsigned long)regs.user_arg4, (unsigned long)regs.user_arg5);
+ nerrs++;
+ } else {
+ printf("[OK]\tRestarted nr and args are correct\n");
+ }
+
+ printf("[RUN]\tChange nr and args and restart the syscall (ip = 0x%lx)\n",
+ (unsigned long)regs.user_ip);
+
+ regs.user_ax = SYS_getpid;
+ regs.user_arg0 = 20;
+ regs.user_arg1 = 21;
+ regs.user_arg2 = 22;
+ regs.user_arg3 = 23;
+ regs.user_arg4 = 24;
+ regs.user_arg5 = 25;
+ regs.user_ip -= 2;
+
+ if (ptrace(PTRACE_SETREGS, chld, 0, ®s) != 0)
+ err(1, "PTRACE_SETREGS");
+
+ if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
+ err(1, "PTRACE_SYSCALL");
+ wait_trap(chld);
+
+ if (ptrace(PTRACE_GETREGS, chld, 0, ®s) != 0)
+ err(1, "PTRACE_GETREGS");
+
+ if (regs.user_syscall_nr != SYS_getpid ||
+ regs.user_arg0 != 20 || regs.user_arg1 != 21 || regs.user_arg2 != 22 ||
+ regs.user_arg3 != 23 || regs.user_arg4 != 24 || regs.user_arg5 != 25) {
+ printf("[FAIL]\tRestart nr or args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", (unsigned long)regs.user_syscall_nr, (unsigned long)regs.user_arg0, (unsigned long)regs.user_arg1, (unsigned long)regs.user_arg2, (unsigned long)regs.user_arg3, (unsigned long)regs.user_arg4, (unsigned long)regs.user_arg5);
+ nerrs++;
+ } else {
+ printf("[OK]\tReplacement nr and args are correct\n");
+ }
+
+ if (ptrace(PTRACE_CONT, chld, 0, 0) != 0)
+ err(1, "PTRACE_CONT");
+ if (waitpid(chld, &status, 0) != chld)
+ err(1, "waitpid");
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ printf("[FAIL]\tChild failed\n");
+ nerrs++;
+ } else {
+ printf("[OK]\tChild exited cleanly\n");
+ }
+}
+
+int main()
+{
+ printf("[RUN]\tCheck int80 return regs\n");
+ test_sys32_regs(do_full_int80);
+
+#if defined(__i386__) && (!defined(__GLIBC__) || __GLIBC__ > 2 || __GLIBC_MINOR__ >= 16)
+ vsyscall32 = (void *)getauxval(AT_SYSINFO);
+ printf("[RUN]\tCheck AT_SYSINFO return regs\n");
+ test_sys32_regs(do_full_vsyscall32);
+#endif
+
+ test_ptrace_syscall_restart();
+
+ return 0;
+}
diff --git a/tools/testing/selftests/x86/raw_syscall_helper_32.S b/tools/testing/selftests/x86/raw_syscall_helper_32.S
new file mode 100644
index 000000000000..d01a13aafc8c
--- /dev/null
+++ b/tools/testing/selftests/x86/raw_syscall_helper_32.S
@@ -0,0 +1,46 @@
+.global sys32_helper
+sys32_helper:
+ /* Args: syscall_args_32*, function pointer */
+ pushl %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+ movl 5*4(%esp), %eax /* pointer to args struct */
+
+ movl 1*4(%eax), %ebx
+ movl 2*4(%eax), %ecx
+ movl 3*4(%eax), %edx
+ movl 4*4(%eax), %esi
+ movl 5*4(%eax), %edi
+ movl 6*4(%eax), %ebp
+ movl 0*4(%eax), %eax
+
+ call *(6*4)(%esp) /* Do the syscall */
+
+ /* Now we need to recover without losing any reg values */
+ pushl %eax
+ movl 6*4(%esp), %eax
+ popl 0*4(%eax)
+ movl %ebx, 1*4(%eax)
+ movl %ecx, 2*4(%eax)
+ movl %edx, 3*4(%eax)
+ movl %esi, 4*4(%eax)
+ movl %edi, 5*4(%eax)
+ movl %ebp, 6*4(%eax)
+
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+
+ .type sys32_helper, @function
+ .size sys32_helper, .-sys32_helper
+
+.global int80_and_ret
+int80_and_ret:
+ int $0x80
+ ret
+
+ .type int80_and_ret, @function
+ .size int80_and_ret, .-int80_and_ret
--
2.4.3
--
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]
| From | Andy Lutomirski <luto@kernel.org> |
|---|---|
| Date | 2015-09-02 01:00 +0200 |
| Subject | [RFC 09/30] x86/vdso: Define BUILD_VDSO while building and emit .eh_frame in asm |
| Message-ID | <q42H0-3xO-33@gated-at.bofh.it> |
| In reply to | #1217129 |
For the vDSO, user code wants runtime unwind info. Make sure that,
if we use .cfi directives, we generate it.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
arch/x86/entry/vdso/Makefile | 4 ++--
arch/x86/include/asm/dwarf2.h | 13 ++++++++++---
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index 3bfb39e7b8b2..265c0ed68118 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -67,7 +67,7 @@ $(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE
CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
$(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
-fno-omit-frame-pointer -foptimize-sibling-calls \
- -DDISABLE_BRANCH_PROFILING
+ -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
$(vobjs): KBUILD_CFLAGS += $(CFL)
@@ -131,7 +131,7 @@ targets += vdso32/vdso32.lds
targets += vdso32/note.o vdso32/vclock_gettime.o vdso32/system_call.o
targets += vdso32/vclock_gettime.o
-KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS))
+KBUILD_AFLAGS_32 := $(filter-out -m64,$(KBUILD_AFLAGS)) -DBUILD_VDSO
$(obj)/vdso32.so.dbg: KBUILD_AFLAGS = $(KBUILD_AFLAGS_32)
$(obj)/vdso32.so.dbg: asflags-$(CONFIG_X86_64) += -m32
diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
index de1cdaf4d743..09133ba032b3 100644
--- a/arch/x86/include/asm/dwarf2.h
+++ b/arch/x86/include/asm/dwarf2.h
@@ -36,15 +36,22 @@
#endif
#if defined(CONFIG_AS_CFI_SECTIONS) && defined(__ASSEMBLY__)
+#ifndef BUILD_VDSO
/*
* Emit CFI data in .debug_frame sections, not .eh_frame sections.
* The latter we currently just discard since we don't do DWARF
* unwinding at runtime. So only the offline DWARF information is
- * useful to anyone. Note we should not use this directive if this
- * file is used in the vDSO assembly, or if vmlinux.lds.S gets
- * changed so it doesn't discard .eh_frame.
+ * useful to anyone. Note we should not use this directive if
+ * vmlinux.lds.S gets changed so it doesn't discard .eh_frame.
*/
.cfi_sections .debug_frame
+#else
+ /*
+ * For the vDSO, emit both runtime unwind information and debug
+ * symbols for the .dbg file.
+ */
+ .cfi_sections .eh_frame, .debug_frame
+#endif
#endif
#else
--
2.4.3
--
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]
| From | Brian Gerst <brgerst@gmail.com> |
|---|---|
| Date | 2015-09-03 07:30 +0200 |
| Message-ID | <q4vfZ-2vQ-15@gated-at.bofh.it> |
| In reply to | #1217129 |
On Tue, Sep 1, 2015 at 6:41 PM, Andy Lutomirski <luto@kernel.org> wrote: > Here's a monster series that I'm working on. I think it's in decent > shape now. > > The first couple patches are tests and some old stuff. There's a > test that validates the vDSO AT_SYSINFO annotations (which fails on > 32-bit Debian systems for some reason that I can't yet fathom > because fast syscalls simply don't happen on my VM for unknown > reasons presumably related to glibc bugs or misconfiguration, and I > need to do something about the test). There's also a test that > exercises some assumptions that signal handling and ptracers make > about syscalls that currently do *not* hold on 64-bit AMD using > 32-bit AT_SYSINFO. > > The next few patches are the NT stuff. Ingo, feel free to pretend > you don't see it until the merge window closes :) > > The rest is basically a rewrite of syscalls for all cases except > 64-bit native. With these patches applied, there is a single 32-bit > vDSO and it uses SYSCALL, SYSENTER, and INT80 almost interchangeably > via alternatives. The semantics of SYSENTER and SYSCALL are defined > as: > > 1. If SYSCALL, ESP = ECX > 2. ECX = *ESP > 3. IP = INT80 landing pad > 4. Opportunistic SYSRET/SYSEXIT is enabled on return > > The vDSO is rearranged so that these semantics work. Anything that > backs IP up by 2 ends up pointing at a bona fide int $0x80 > instruction with the expected regs. > > In the process, the vDSO CFI annotations (which are actually used) > get rewritten using normal CFI directives. > > Opportunistic SYSRET/SYSEXIT only happens on return when CS and SS > are as expected, IP points to the INT80 landing pad, and flags are > in good shape. I think the opportunistic exit code could be improved a bit more. The checks are only be necessary if force_iret() was called meaning registers were changed. One possibility is to add a ti->status flag TS_FASTSYSCALL. Then we could move the tests to force_iret(), which would clear the flag if the registers fail validation. The syscall exit path then would check the flag and exit via IRET if it's clear. That would reduce the impact of the tests on the fast path where no regs were changed. > Other than that, the system call entries are simplified to the bare > minimum prologue and a call to a C function. Amusingly, SYSENTER > and SYSCALL32 use the same C function. > > To make that work, I had to remove all the 32-bit syscall stubs > except the clone argument hack. This is because, for C code to call > through the system call table, the system call table entries need to > be real function pointers with C-compatible ABIs. > > There is nothing at all anymore that requires that x86_32 syscalls > be asmlinkage. That could be removed in a subsequent patch. Other arches (at least IA-64) still need asmlinkage or something equivalent for their syscalls. asmlinkage_protect() can also be removed. > The upshot appears to be a ~25 cycle performance hit on 32-bit fast > path syscalls. The slow path is probably faster under most > circumstances and, if the exit slow path gets hit, it'll be much > faster because (as we already do in the 64-bit native case) we can > still use SYSEXIT/SYSRET. > > The patchset is structured as a removal of the old fast syscall > code, then the change that makes syscalls into real functions, then > a clean re-implementation of fast syscalls. > > If we want some of the 25 cycles back, we could consider open-coding > a new C fast path. Is the 25 cycles for the compat or native case? I'd expect the native case to be hit harder because of register pressure. -- 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]
| From | Andy Lutomirski <luto@amacapital.net> |
|---|---|
| Date | 2015-09-03 19:20 +0200 |
| Message-ID | <q4Gl4-1yZ-19@gated-at.bofh.it> |
| In reply to | #1218045 |
On Wed, Sep 2, 2015 at 10:23 PM, Brian Gerst <brgerst@gmail.com> wrote: > On Tue, Sep 1, 2015 at 6:41 PM, Andy Lutomirski <luto@kernel.org> wrote: >> Here's a monster series that I'm working on. I think it's in decent >> shape now. >> >> The first couple patches are tests and some old stuff. There's a >> test that validates the vDSO AT_SYSINFO annotations (which fails on >> 32-bit Debian systems for some reason that I can't yet fathom >> because fast syscalls simply don't happen on my VM for unknown >> reasons presumably related to glibc bugs or misconfiguration, and I >> need to do something about the test). There's also a test that >> exercises some assumptions that signal handling and ptracers make >> about syscalls that currently do *not* hold on 64-bit AMD using >> 32-bit AT_SYSINFO. >> >> The next few patches are the NT stuff. Ingo, feel free to pretend >> you don't see it until the merge window closes :) >> >> The rest is basically a rewrite of syscalls for all cases except >> 64-bit native. With these patches applied, there is a single 32-bit >> vDSO and it uses SYSCALL, SYSENTER, and INT80 almost interchangeably >> via alternatives. The semantics of SYSENTER and SYSCALL are defined >> as: >> >> 1. If SYSCALL, ESP = ECX >> 2. ECX = *ESP >> 3. IP = INT80 landing pad >> 4. Opportunistic SYSRET/SYSEXIT is enabled on return >> >> The vDSO is rearranged so that these semantics work. Anything that >> backs IP up by 2 ends up pointing at a bona fide int $0x80 >> instruction with the expected regs. >> >> In the process, the vDSO CFI annotations (which are actually used) >> get rewritten using normal CFI directives. >> >> Opportunistic SYSRET/SYSEXIT only happens on return when CS and SS >> are as expected, IP points to the INT80 landing pad, and flags are >> in good shape. > > I think the opportunistic exit code could be improved a bit more. The > checks are only be necessary if force_iret() was called meaning > registers were changed. One possibility is to add a ti->status flag > TS_FASTSYSCALL. Then we could move the tests to force_iret(), which > would clear the flag if the registers fail validation. The syscall > exit path then would check the flag and exit via IRET if it's clear. > That would reduce the impact of the tests on the fast path where no > regs were changed. Historically, it's not just force_iret() (which is quite new) but anything that triggers the slow path. If we want to go that route, I'd be more comfortable doing something more like: if (!(ti->flags & _TIF_SYSCALL_EXIT_WORK)) return true; i.e. just bypassing the slow path exit and the check. This might get some more of those cycles back for the full fast path, albeit at the cost of more complexity in the C code. Maybe some day we should add better accessors for pt_regs that warn if misused and set flags if used for write. For example, const struct pt_regs *syscall_pt_regs_read() and struct pt_regs *syscall_pt_regs_write(). The latter could set a flag. > >> Other than that, the system call entries are simplified to the bare >> minimum prologue and a call to a C function. Amusingly, SYSENTER >> and SYSCALL32 use the same C function. >> >> To make that work, I had to remove all the 32-bit syscall stubs >> except the clone argument hack. This is because, for C code to call >> through the system call table, the system call table entries need to >> be real function pointers with C-compatible ABIs. >> >> There is nothing at all anymore that requires that x86_32 syscalls >> be asmlinkage. That could be removed in a subsequent patch. > > Other arches (at least IA-64) still need asmlinkage or something > equivalent for their syscalls. We should probably add a macro syscall_abi that expands to nothing on x86 and to asmlinkage on IA-64. (Why asm "linkage"? It has nothing to do with linkage.) > > asmlinkage_protect() can also be removed. Wow, that's gross. I'm a bit surprised that no new compiler has clever enough to break that hack. > >> The upshot appears to be a ~25 cycle performance hit on 32-bit fast >> path syscalls. The slow path is probably faster under most >> circumstances and, if the exit slow path gets hit, it'll be much >> faster because (as we already do in the 64-bit native case) we can >> still use SYSEXIT/SYSRET. >> >> The patchset is structured as a removal of the old fast syscall >> code, then the change that makes syscalls into real functions, then >> a clean re-implementation of fast syscalls. >> >> If we want some of the 25 cycles back, we could consider open-coding >> a new C fast path. > > Is the 25 cycles for the compat or native case? I'd expect the native > case to be hit harder because of register pressure. Compat, which I find easier to benchmark because my 32-bit VM steadfastly refuses to issue syscalls via AT_SYSINFO. (I can do it manually, and static binaries built elsewhere work fine, but something's wrong with its glibc.) I'll benchmark native 32-bit soon. --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] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | linux.kernel
csiph-web