Commit a359bb11 authored by Martin Schwidefsky's avatar Martin Schwidefsky

s390/kernel: squeeze a few more cycles out of the system call handler

Reorder the instructions of UPDATE_VTIME to improve superscalar execution,
remove duplicate checks for problem-state from the asynchronous interrupt
handlers, and move the check for problem-state from the synchronous
exit path to the program check path as it is only needed for program
checks inside the kernel.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent d0fc4107
...@@ -83,7 +83,7 @@ _PIF_WORK = (_PIF_PER_TRAP) ...@@ -83,7 +83,7 @@ _PIF_WORK = (_PIF_PER_TRAP)
#endif #endif
.endm .endm
.macro SWITCH_ASYNC savearea,stack,shift .macro SWITCH_ASYNC savearea,stack,shift,timer
tmhh %r8,0x0001 # interrupting from user ? tmhh %r8,0x0001 # interrupting from user ?
jnz 1f jnz 1f
lgr %r14,%r9 lgr %r14,%r9
...@@ -97,23 +97,25 @@ _PIF_WORK = (_PIF_PER_TRAP) ...@@ -97,23 +97,25 @@ _PIF_WORK = (_PIF_PER_TRAP)
0: lg %r14,\stack # are we already on the target stack? 0: lg %r14,\stack # are we already on the target stack?
slgr %r14,%r15 slgr %r14,%r15
srag %r14,%r14,\shift srag %r14,%r14,\shift
jnz 1f jnz 2f
CHECK_STACK 1<<\shift,\savearea CHECK_STACK 1<<\shift,\savearea
aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j 2f j 3f
1: lg %r15,\stack # load target stack 1: LAST_BREAK %r14
2: la %r11,STACK_FRAME_OVERHEAD(%r15) UPDATE_VTIME %r14,%r15,\timer
2: lg %r15,\stack # load target stack
3: la %r11,STACK_FRAME_OVERHEAD(%r15)
.endm .endm
.macro UPDATE_VTIME scratch,enter_timer .macro UPDATE_VTIME w1,w2,enter_timer
lg \scratch,__LC_EXIT_TIMER lg \w1,__LC_EXIT_TIMER
slg \scratch,\enter_timer lg \w2,__LC_LAST_UPDATE_TIMER
alg \scratch,__LC_USER_TIMER slg \w1,\enter_timer
stg \scratch,__LC_USER_TIMER slg \w2,__LC_EXIT_TIMER
lg \scratch,__LC_LAST_UPDATE_TIMER alg \w1,__LC_USER_TIMER
slg \scratch,__LC_EXIT_TIMER alg \w2,__LC_SYSTEM_TIMER
alg \scratch,__LC_SYSTEM_TIMER stg \w1,__LC_USER_TIMER
stg \scratch,__LC_SYSTEM_TIMER stg \w2,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),\enter_timer mvc __LC_LAST_UPDATE_TIMER(8),\enter_timer
.endm .endm
...@@ -246,9 +248,9 @@ ENTRY(system_call) ...@@ -246,9 +248,9 @@ ENTRY(system_call)
.Lsysc_per: .Lsysc_per:
lg %r15,__LC_KERNEL_STACK lg %r15,__LC_KERNEL_STACK
la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
.Lsysc_vtime:
UPDATE_VTIME %r13,__LC_SYNC_ENTER_TIMER
LAST_BREAK %r13 LAST_BREAK %r13
.Lsysc_vtime:
UPDATE_VTIME %r10,%r13,__LC_SYNC_ENTER_TIMER
stmg %r0,%r7,__PT_R0(%r11) stmg %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW
...@@ -278,8 +280,6 @@ ENTRY(system_call) ...@@ -278,8 +280,6 @@ ENTRY(system_call)
.Lsysc_return: .Lsysc_return:
LOCKDEP_SYS_EXIT LOCKDEP_SYS_EXIT
.Lsysc_tif: .Lsysc_tif:
tm __PT_PSW+1(%r11),0x01 # returning to user ?
jno .Lsysc_restore
tm __PT_FLAGS+7(%r11),_PIF_WORK tm __PT_FLAGS+7(%r11),_PIF_WORK
jnz .Lsysc_work jnz .Lsysc_work
tm __TI_flags+7(%r12),_TIF_WORK tm __TI_flags+7(%r12),_TIF_WORK
...@@ -467,8 +467,8 @@ ENTRY(pgm_check_handler) ...@@ -467,8 +467,8 @@ ENTRY(pgm_check_handler)
1: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC 1: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC
aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j 3f j 3f
2: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER 2: LAST_BREAK %r14
LAST_BREAK %r14 UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
lg %r15,__LC_KERNEL_STACK lg %r15,__LC_KERNEL_STACK
lg %r14,__TI_task(%r12) lg %r14,__TI_task(%r12)
aghi %r14,__TASK_thread # pointer to thread_struct aghi %r14,__TASK_thread # pointer to thread_struct
...@@ -498,11 +498,15 @@ ENTRY(pgm_check_handler) ...@@ -498,11 +498,15 @@ ENTRY(pgm_check_handler)
llgh %r10,__PT_INT_CODE+2(%r11) llgh %r10,__PT_INT_CODE+2(%r11)
nill %r10,0x007f nill %r10,0x007f
sll %r10,2 sll %r10,2
je .Lsysc_return je .Lpgm_return
lgf %r1,0(%r10,%r1) # load address of handler routine lgf %r1,0(%r10,%r1) # load address of handler routine
lgr %r2,%r11 # pass pointer to pt_regs lgr %r2,%r11 # pass pointer to pt_regs
basr %r14,%r1 # branch to interrupt-handler basr %r14,%r1 # branch to interrupt-handler
j .Lsysc_return .Lpgm_return:
LOCKDEP_SYS_EXIT
tm __PT_PSW+1(%r11),0x01 # returning to user ?
jno .Lsysc_restore
j .Lsysc_tif
# #
# PER event in supervisor state, must be kprobes # PER event in supervisor state, must be kprobes
...@@ -512,7 +516,7 @@ ENTRY(pgm_check_handler) ...@@ -512,7 +516,7 @@ ENTRY(pgm_check_handler)
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
lgr %r2,%r11 # pass pointer to pt_regs lgr %r2,%r11 # pass pointer to pt_regs
brasl %r14,do_per_trap brasl %r14,do_per_trap
j .Lsysc_return j .Lpgm_return
# #
# single stepped system call # single stepped system call
...@@ -535,12 +539,8 @@ ENTRY(io_int_handler) ...@@ -535,12 +539,8 @@ ENTRY(io_int_handler)
lg %r12,__LC_THREAD_INFO lg %r12,__LC_THREAD_INFO
larl %r13,cleanup_critical larl %r13,cleanup_critical
lmg %r8,%r9,__LC_IO_OLD_PSW lmg %r8,%r9,__LC_IO_OLD_PSW
SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT,\
tmhh %r8,0x0001 # interrupting from user? __LC_ASYNC_ENTER_TIMER
jz .Lio_skip
UPDATE_VTIME %r14,__LC_ASYNC_ENTER_TIMER
LAST_BREAK %r14
.Lio_skip:
stmg %r0,%r7,__PT_R0(%r11) stmg %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
stmg %r8,%r9,__PT_PSW(%r11) stmg %r8,%r9,__PT_PSW(%r11)
...@@ -712,12 +712,8 @@ ENTRY(ext_int_handler) ...@@ -712,12 +712,8 @@ ENTRY(ext_int_handler)
lg %r12,__LC_THREAD_INFO lg %r12,__LC_THREAD_INFO
larl %r13,cleanup_critical larl %r13,cleanup_critical
lmg %r8,%r9,__LC_EXT_OLD_PSW lmg %r8,%r9,__LC_EXT_OLD_PSW
SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT,\
tmhh %r8,0x0001 # interrupting from user ? __LC_ASYNC_ENTER_TIMER
jz .Lext_skip
UPDATE_VTIME %r14,__LC_ASYNC_ENTER_TIMER
LAST_BREAK %r14
.Lext_skip:
stmg %r0,%r7,__PT_R0(%r11) stmg %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC mvc __PT_R8(64,%r11),__LC_SAVE_AREA_ASYNC
stmg %r8,%r9,__PT_PSW(%r11) stmg %r8,%r9,__PT_PSW(%r11)
...@@ -896,11 +892,8 @@ ENTRY(mcck_int_handler) ...@@ -896,11 +892,8 @@ ENTRY(mcck_int_handler)
mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) mvc __LC_MCCK_ENTER_TIMER(8),0(%r14)
3: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 3: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
jno .Lmcck_panic # no -> skip cleanup critical jno .Lmcck_panic # no -> skip cleanup critical
SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+64,__LC_PANIC_STACK,PAGE_SHIFT SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+64,__LC_PANIC_STACK,PAGE_SHIFT,\
tm %r8,0x0001 # interrupting from user ? __LC_MCCK_ENTER_TIMER
jz .Lmcck_skip
UPDATE_VTIME %r14,__LC_MCCK_ENTER_TIMER
LAST_BREAK %r14
.Lmcck_skip: .Lmcck_skip:
lghi %r14,__LC_GPREGS_SAVE_AREA+64 lghi %r14,__LC_GPREGS_SAVE_AREA+64
stmg %r0,%r7,__PT_R0(%r11) stmg %r0,%r7,__PT_R0(%r11)
...@@ -1125,7 +1118,7 @@ cleanup_critical: ...@@ -1125,7 +1118,7 @@ cleanup_critical:
.quad system_call .quad system_call
.quad .Lsysc_stmg .quad .Lsysc_stmg
.quad .Lsysc_per .quad .Lsysc_per
.quad .Lsysc_vtime+18 .quad .Lsysc_vtime+36
.quad .Lsysc_vtime+42 .quad .Lsysc_vtime+42
.Lcleanup_sysc_tif: .Lcleanup_sysc_tif:
......
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