Commit 61649881 authored by Martin Schwidefsky's avatar Martin Schwidefsky

s390: system call path micro optimization

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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent dc7ee00d
...@@ -120,6 +120,7 @@ ...@@ -120,6 +120,7 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/compat.h> #include <asm/compat.h>
#include <asm/syscall.h>
#include <asm/user.h> #include <asm/user.h>
typedef s390_fp_regs elf_fpregset_t; typedef s390_fp_regs elf_fpregset_t;
...@@ -181,18 +182,31 @@ extern unsigned long elf_hwcap; ...@@ -181,18 +182,31 @@ extern unsigned long elf_hwcap;
extern char elf_platform[]; extern char elf_platform[];
#define ELF_PLATFORM (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) \ #define SET_PERSONALITY(ex) \
do { \ do { \
if (personality(current->personality) != PER_LINUX32) \ if (personality(current->personality) != PER_LINUX32) \
set_personality(PER_LINUX | \ set_personality(PER_LINUX | \
(current->personality & ~PER_MASK)); \ (current->personality & ~PER_MASK)); \
if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ if ((ex).e_ident[EI_CLASS] == ELFCLASS32) { \
set_thread_flag(TIF_31BIT); \ set_thread_flag(TIF_31BIT); \
else \ current_thread_info()->sys_call_table = \
(unsigned long) &sys_call_table_emu; \
} else { \
clear_thread_flag(TIF_31BIT); \ clear_thread_flag(TIF_31BIT); \
current_thread_info()->sys_call_table = \
(unsigned long) &sys_call_table; \
} \
} while (0) } while (0)
#endif /* CONFIG_64BIT */ #endif /* CONFIG_COMPAT */
#define STACK_RND_MASK 0x7ffUL #define STACK_RND_MASK 0x7ffUL
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
* type here is what we want [need] for both 32 bit and 64 bit systems. * 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[];
extern const unsigned int sys_call_table_emu[];
static inline long syscall_get_nr(struct task_struct *task, static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs) struct pt_regs *regs)
......
...@@ -41,6 +41,7 @@ struct thread_info { ...@@ -41,6 +41,7 @@ struct thread_info {
struct task_struct *task; /* main task structure */ struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */ struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
unsigned long sys_call_table; /* System call table address */
unsigned int cpu; /* current CPU */ unsigned int cpu; /* current CPU */
int preempt_count; /* 0 => preemptable, <0 => BUG */ int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block; struct restart_block restart_block;
......
...@@ -35,6 +35,7 @@ int main(void) ...@@ -35,6 +35,7 @@ int main(void)
DEFINE(__TI_task, offsetof(struct thread_info, task)); DEFINE(__TI_task, offsetof(struct thread_info, task));
DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain)); DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain));
DEFINE(__TI_flags, offsetof(struct thread_info, flags)); 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_cpu, offsetof(struct thread_info, cpu));
DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count)); DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));
DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer)); DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer));
......
...@@ -188,6 +188,7 @@ sysc_vtime: ...@@ -188,6 +188,7 @@ sysc_vtime:
mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
sysc_do_svc: sysc_do_svc:
oi __TI_flags+3(%r12),_TIF_SYSCALL 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) lh %r8,__PT_INT_CODE+2(%r11)
sla %r8,2 # shift and test for svc0 sla %r8,2 # shift and test for svc0
jnz sysc_nr_ok jnz sysc_nr_ok
...@@ -198,7 +199,6 @@ sysc_do_svc: ...@@ -198,7 +199,6 @@ sysc_do_svc:
lr %r8,%r1 lr %r8,%r1
sla %r8,2 sla %r8,2
sysc_nr_ok: sysc_nr_ok:
l %r10,BASED(.Lsys_call_table) # 31 bit system call table
xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
st %r2,__PT_ORIG_GPR2(%r11) st %r2,__PT_ORIG_GPR2(%r11)
st %r7,STACK_FRAME_OVERHEAD(%r15) st %r7,STACK_FRAME_OVERHEAD(%r15)
...@@ -906,7 +906,6 @@ cleanup_idle_wait: ...@@ -906,7 +906,6 @@ cleanup_idle_wait:
.Ltrace_enter: .long do_syscall_trace_enter .Ltrace_enter: .long do_syscall_trace_enter
.Ltrace_exit: .long do_syscall_trace_exit .Ltrace_exit: .long do_syscall_trace_exit
.Lschedule_tail: .long schedule_tail .Lschedule_tail: .long schedule_tail
.Lsys_call_table: .long sys_call_table
.Lsysc_per: .long sysc_per + 0x80000000 .Lsysc_per: .long sysc_per + 0x80000000
#ifdef CONFIG_TRACE_IRQFLAGS #ifdef CONFIG_TRACE_IRQFLAGS
.Lhardirqs_on: .long trace_hardirqs_on_caller .Lhardirqs_on: .long trace_hardirqs_on_caller
......
...@@ -216,6 +216,7 @@ sysc_vtime: ...@@ -216,6 +216,7 @@ sysc_vtime:
mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
sysc_do_svc: sysc_do_svc:
oi __TI_flags+7(%r12),_TIF_SYSCALL 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) llgh %r8,__PT_INT_CODE+2(%r11)
slag %r8,%r8,2 # shift and test for svc 0 slag %r8,%r8,2 # shift and test for svc 0
jnz sysc_nr_ok jnz sysc_nr_ok
...@@ -226,13 +227,6 @@ sysc_do_svc: ...@@ -226,13 +227,6 @@ sysc_do_svc:
sth %r1,__PT_INT_CODE+2(%r11) sth %r1,__PT_INT_CODE+2(%r11)
slag %r8,%r1,2 slag %r8,%r1,2
sysc_nr_ok: 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) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
stg %r2,__PT_ORIG_GPR2(%r11) stg %r2,__PT_ORIG_GPR2(%r11)
stg %r7,STACK_FRAME_OVERHEAD(%r15) stg %r7,STACK_FRAME_OVERHEAD(%r15)
...@@ -1005,6 +999,7 @@ sys_call_table: ...@@ -1005,6 +999,7 @@ sys_call_table:
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
#define SYSCALL(esa,esame,emu) .long emu #define SYSCALL(esa,esame,emu) .long emu
.globl sys_call_table_emu
sys_call_table_emu: sys_call_table_emu:
#include "syscalls.S" #include "syscalls.S"
#undef SYSCALL #undef SYSCALL
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment