s390: system call path micro optimization
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 24 Apr 2013 10:58:39 +0000 (12:58 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 26 Apr 2013 07:07:05 +0000 (09:07 +0200)
Add a pointer to the system call table to the thread_info structure.
The TIF_31BIT bit is set or cleared by SET_PERSONALITY exactly once
for the lifetime of a process. With the pointer to the correct system
call table in thread_info the system call code in entry64.S path can
drop the check for TIF_31BIT which saves a couple of instructions.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/elf.h
arch/s390/include/asm/syscall.h
arch/s390/include/asm/thread_info.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S

index 27ec2c3f95acb3dd8219a7ef1e80dc7388a375d8..78f4f8711d58a78f0a3e277b13719bd1514f38ea 100644 (file)
 
 #include <asm/ptrace.h>
 #include <asm/compat.h>
+#include <asm/syscall.h>
 #include <asm/user.h>
 
 typedef s390_fp_regs elf_fpregset_t;
@@ -181,18 +182,31 @@ extern unsigned long elf_hwcap;
 extern char elf_platform[];
 #define ELF_PLATFORM (elf_platform)
 
-#ifdef CONFIG_64BIT
+#ifndef CONFIG_COMPAT
+#define SET_PERSONALITY(ex) \
+do {                                                           \
+       set_personality(PER_LINUX |                             \
+               (current->personality & (~PER_MASK)));          \
+       current_thread_info()->sys_call_table =                 \
+               (unsigned long) &sys_call_table;                \
+} while (0)
+#else /* CONFIG_COMPAT */
 #define SET_PERSONALITY(ex)                                    \
 do {                                                           \
        if (personality(current->personality) != PER_LINUX32)   \
                set_personality(PER_LINUX |                     \
                        (current->personality & ~PER_MASK));    \
-       if ((ex).e_ident[EI_CLASS] == ELFCLASS32)               \
+       if ((ex).e_ident[EI_CLASS] == ELFCLASS32) {             \
                set_thread_flag(TIF_31BIT);                     \
-       else                                                    \
+               current_thread_info()->sys_call_table =         \
+                       (unsigned long) &sys_call_table_emu;    \
+       } else {                                                \
                clear_thread_flag(TIF_31BIT);                   \
+               current_thread_info()->sys_call_table =         \
+                       (unsigned long) &sys_call_table;        \
+       }                                                       \
 } while (0)
-#endif /* CONFIG_64BIT */
+#endif /* CONFIG_COMPAT */
 
 #define STACK_RND_MASK 0x7ffUL
 
index fe7b99759e12ffcdf5f2df9880f86f91df3c9800..cd29d2f4e4f355512ecbafd0cfcc0c7fab05042a 100644 (file)
@@ -23,6 +23,7 @@
  * type here is what we want [need] for both 32 bit and 64 bit systems.
  */
 extern const unsigned int sys_call_table[];
+extern const unsigned int sys_call_table_emu[];
 
 static inline long syscall_get_nr(struct task_struct *task,
                                  struct pt_regs *regs)
index 9e2cfe0349c3c5f50177a870ba6061ec7bd85dd0..51035e5d86cbe7319b07dc570fbb4af131f51cdc 100644 (file)
@@ -41,6 +41,7 @@ struct thread_info {
        struct task_struct      *task;          /* main task structure */
        struct exec_domain      *exec_domain;   /* execution domain */
        unsigned long           flags;          /* low level flags */
+       unsigned long           sys_call_table; /* System call table address */
        unsigned int            cpu;            /* current CPU */
        int                     preempt_count;  /* 0 => preemptable, <0 => BUG */
        struct restart_block    restart_block;
index fface87056eb6f50357ae0d376ee55ccbb972e87..7a82f9f7010015e4d73349a1a46426017a4088dd 100644 (file)
@@ -35,6 +35,7 @@ int main(void)
        DEFINE(__TI_task, offsetof(struct thread_info, task));
        DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain));
        DEFINE(__TI_flags, offsetof(struct thread_info, flags));
+       DEFINE(__TI_sysc_table, offsetof(struct thread_info, sys_call_table));
        DEFINE(__TI_cpu, offsetof(struct thread_info, cpu));
        DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));
        DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer));
index 17d5cc0578930ae8fa024021694161371cf8acb6..4d5e6f8a7978cb005d0ae15fe3d1837175f285d1 100644 (file)
@@ -188,6 +188,7 @@ sysc_vtime:
        mvc     __PT_INT_CODE(4,%r11),__LC_SVC_ILC
 sysc_do_svc:
        oi      __TI_flags+3(%r12),_TIF_SYSCALL
+       l       %r10,__TI_sysc_table(%r12)      # 31 bit system call table
        lh      %r8,__PT_INT_CODE+2(%r11)
        sla     %r8,2                           # shift and test for svc0
        jnz     sysc_nr_ok
@@ -198,7 +199,6 @@ sysc_do_svc:
        lr      %r8,%r1
        sla     %r8,2
 sysc_nr_ok:
-       l       %r10,BASED(.Lsys_call_table)    # 31 bit system call table
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
        st      %r2,__PT_ORIG_GPR2(%r11)
        st      %r7,STACK_FRAME_OVERHEAD(%r15)
@@ -906,7 +906,6 @@ cleanup_idle_wait:
 .Ltrace_enter:         .long   do_syscall_trace_enter
 .Ltrace_exit:          .long   do_syscall_trace_exit
 .Lschedule_tail:       .long   schedule_tail
-.Lsys_call_table:      .long   sys_call_table
 .Lsysc_per:            .long   sysc_per + 0x80000000
 #ifdef CONFIG_TRACE_IRQFLAGS
 .Lhardirqs_on:         .long   trace_hardirqs_on_caller
index 72f230baf5d1a91665c6364b3dc619930a054fac..4c17eece707eb94d0b08c55b63a25b7788fb0c56 100644 (file)
@@ -216,6 +216,7 @@ sysc_vtime:
        mvc     __PT_INT_CODE(4,%r11),__LC_SVC_ILC
 sysc_do_svc:
        oi      __TI_flags+7(%r12),_TIF_SYSCALL
+       lg      %r10,__TI_sysc_table(%r12)      # address of system call table
        llgh    %r8,__PT_INT_CODE+2(%r11)
        slag    %r8,%r8,2                       # shift and test for svc 0
        jnz     sysc_nr_ok
@@ -226,13 +227,6 @@ sysc_do_svc:
        sth     %r1,__PT_INT_CODE+2(%r11)
        slag    %r8,%r1,2
 sysc_nr_ok:
-       larl    %r10,sys_call_table             # 64 bit system call table
-#ifdef CONFIG_COMPAT
-       tm      __TI_flags+5(%r12),(_TIF_31BIT>>16)
-       jno     sysc_noemu
-       larl    %r10,sys_call_table_emu         # 31 bit system call table
-sysc_noemu:
-#endif
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
        stg     %r2,__PT_ORIG_GPR2(%r11)
        stg     %r7,STACK_FRAME_OVERHEAD(%r15)
@@ -1005,6 +999,7 @@ sys_call_table:
 #ifdef CONFIG_COMPAT
 
 #define SYSCALL(esa,esame,emu) .long emu
+       .globl  sys_call_table_emu
 sys_call_table_emu:
 #include "syscalls.S"
 #undef SYSCALL