Skip to content

Commit

Permalink
[S390] cleanup trap handling
Browse files Browse the repository at this point in the history
Move the program interruption code and the translation exception identifier
to the pt_regs structure as 'int_code' and 'int_parm_long' and make the
first level interrupt handler in entry[64].S store the two values. That
makes it possible to drop 'prot_addr' and 'trap_no' from the thread_struct
and to reduce the number of arguments to a lot of functions. Finally
un-inline do_trap. Overall this saves 5812 bytes in the .text section of
the 64 bit kernel.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Martin Schwidefsky committed Dec 27, 2011
1 parent 679e2ea commit aa33c8c
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 210 deletions.
2 changes: 1 addition & 1 deletion arch/s390/include/asm/kdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ enum die_val {
DIE_NMI_IPI,
};

extern void die(const char *, struct pt_regs *, long);
extern void die(struct pt_regs *, const char *);

#endif
2 changes: 0 additions & 2 deletions arch/s390/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ struct thread_struct {
unsigned int acrs[NUM_ACRS];
unsigned long ksp; /* kernel stack pointer */
mm_segment_t mm_segment;
unsigned long prot_addr; /* address of protection-excep. */
unsigned int trap_no;
unsigned long gmap_addr; /* address of last gmap fault. */
struct per_regs per_user; /* User specified PER registers */
struct per_event per_event; /* Cause of the last PER trap */
Expand Down
3 changes: 2 additions & 1 deletion arch/s390/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,8 @@ struct pt_regs
psw_t psw;
unsigned long gprs[NUM_GPRS];
unsigned long orig_gpr2;
unsigned int svc_code;
unsigned int int_code;
unsigned long int_parm_long;
};

/*
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs)
{
return test_tsk_thread_flag(task, TIF_SYSCALL) ?
(regs->svc_code & 0xffff) : -1;
(regs->int_code & 0xffff) : -1;
}

static inline void syscall_rollback(struct task_struct *task,
Expand Down
3 changes: 2 additions & 1 deletion arch/s390/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ int main(void)
DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
DEFINE(__PT_SVC_CODE, offsetof(struct pt_regs, svc_code));
DEFINE(__PT_INT_CODE, offsetof(struct pt_regs, int_code));
DEFINE(__PT_INT_PARM_LONG, offsetof(struct pt_regs, int_parm_long));
DEFINE(__PT_SIZE, sizeof(struct pt_regs));
BLANK();
DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
Expand Down
8 changes: 6 additions & 2 deletions arch/s390/kernel/compat_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,12 @@ static int setup_frame32(int sig, struct k_sigaction *ka,

/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility, they are passed as args. */
regs->gprs[4] = current->thread.trap_no;
regs->gprs[5] = current->thread.prot_addr;
if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
sig == SIGTRAP || sig == SIGFPE) {
/* set extra registers only for synchronous signals */
regs->gprs[4] = regs->int_code & 127;
regs->gprs[5] = regs->int_parm_long;
}

/* Place signal number on stack to allow backtrace from handler. */
if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
Expand Down
22 changes: 11 additions & 11 deletions arch/s390/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -184,16 +184,16 @@ sysc_vtime:
stm %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC
mvc __PT_PSW(8,%r11),__LC_SVC_OLD_PSW
mvc __PT_SVC_CODE(4,%r11),__LC_SVC_ILC
mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
sysc_do_svc:
oi __TI_flags+3(%r12),_TIF_SYSCALL
lh %r8,__PT_SVC_CODE+2(%r11)
lh %r8,__PT_INT_CODE+2(%r11)
sla %r8,2 # shift and test for svc0
jnz sysc_nr_ok
# svc 0: system call number in %r1
cl %r1,BASED(.Lnr_syscalls)
jnl sysc_nr_ok
sth %r1,__PT_SVC_CODE+2(%r11)
sth %r1,__PT_INT_CODE+2(%r11)
lr %r8,%r1
sla %r8,2
sysc_nr_ok:
Expand Down Expand Up @@ -266,9 +266,9 @@ sysc_sigpending:
jno sysc_return
lm %r2,%r7,__PT_R2(%r11) # load svc arguments
xr %r8,%r8 # svc 0 returns -ENOSYS
clc __PT_SVC_CODE+2(2,%r11),BASED(.Lnr_syscalls+2)
clc __PT_INT_CODE+2(2,%r11),BASED(.Lnr_syscalls+2)
jnl sysc_nr_ok # invalid svc number -> do svc 0
lh %r8,__PT_SVC_CODE+2(%r11) # load new svc number
lh %r8,__PT_INT_CODE+2(%r11) # load new svc number
sla %r8,2
j sysc_nr_ok # restart svc

Expand Down Expand Up @@ -300,7 +300,7 @@ sysc_tracesys:
lr %r2,%r11 # pass pointer to pt_regs
la %r3,0
xr %r0,%r0
icm %r0,3,__PT_SVC_CODE+2(%r11)
icm %r0,3,__PT_INT_CODE+2(%r11)
st %r0,__PT_R2(%r11)
basr %r14,%r1 # call do_syscall_trace_enter
cl %r2,BASED(.Lnr_syscalls)
Expand Down Expand Up @@ -396,6 +396,8 @@ ENTRY(pgm_check_handler)
stm %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC
stm %r8,%r9,__PT_PSW(%r11)
mvc __PT_INT_CODE(4,%r11),__LC_PGM_ILC
mvc __PT_INT_PARM_LONG(4,%r11),__LC_TRANS_EXC_CODE
tm __LC_PGM_ILC+3,0x80 # check for per exception
jz 0f
l %r1,__TI_task(%r12)
Expand All @@ -405,13 +407,11 @@ ENTRY(pgm_check_handler)
mvc __THREAD_per_address(4,%r1),__LC_PER_ADDRESS
mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE
mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID
0: l %r3,__LC_PGM_ILC # load program interruption code
l %r4,__LC_TRANS_EXC_CODE
REENABLE_IRQS
0: REENABLE_IRQS
xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
l %r1,BASED(.Ljump_table)
la %r10,0x7f
nr %r10,%r3
n %r10,__PT_INT_CODE(%r11)
je sysc_return
sll %r10,2
l %r1,0(%r10,%r1) # load address of handler routine
Expand Down Expand Up @@ -858,7 +858,7 @@ cleanup_system_call:
mvc __PT_R8(32,%r15),__LC_SAVE_AREA_SYNC
stm %r0,%r7,__PT_R0(%r15)
mvc __PT_PSW(8,%r15),__LC_SVC_OLD_PSW
mvc __PT_SVC_CODE(4,%r15),__LC_SVC_ILC
mvc __PT_INT_CODE(4,%r15),__LC_SVC_ILC
# setup saved register 15
ahi %r15,-STACK_FRAME_OVERHEAD
st %r15,28(%r11) # r15 stack pointer
Expand Down
10 changes: 5 additions & 5 deletions arch/s390/kernel/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
#include <asm/ptrace.h>


extern void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long);
extern void (*pgm_check_table[128])(struct pt_regs *);
extern void *restart_stack;

asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);

void do_protection_exception(struct pt_regs *, long, unsigned long);
void do_dat_exception(struct pt_regs *, long, unsigned long);
void do_asce_exception(struct pt_regs *, long, unsigned long);
void do_protection_exception(struct pt_regs *regs);
void do_dat_exception(struct pt_regs *regs);
void do_asce_exception(struct pt_regs *regs);

void do_per_trap(struct pt_regs *regs);
void syscall_trace(struct pt_regs *regs, int entryexit);
Expand All @@ -28,7 +28,7 @@ void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
void do_restart(void);
int __cpuinit start_secondary(void *cpuvoid);
void __init startup_init(void);
void die(const char * str, struct pt_regs * regs, long err);
void die(struct pt_regs *regs, const char *str);

void __init time_init(void);

Expand Down
27 changes: 13 additions & 14 deletions arch/s390/kernel/entry64.S
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/*
* arch/s390/kernel/entry64.S
* S390 low-level entry points.
Expand Down Expand Up @@ -200,17 +199,17 @@ sysc_vtime:
stmg %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW
mvc __PT_SVC_CODE(4,%r11),__LC_SVC_ILC
mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
sysc_do_svc:
oi __TI_flags+7(%r12),_TIF_SYSCALL
llgh %r8,__PT_SVC_CODE+2(%r11)
llgh %r8,__PT_INT_CODE+2(%r11)
slag %r8,%r8,2 # shift and test for svc 0
jnz sysc_nr_ok
# svc 0: system call number in %r1
llgfr %r1,%r1 # clear high word in r1
cghi %r1,NR_syscalls
jnl sysc_nr_ok
sth %r1,__PT_SVC_CODE+2(%r11)
sth %r1,__PT_INT_CODE+2(%r11)
slag %r8,%r1,2
sysc_nr_ok:
larl %r10,sys_call_table # 64 bit system call table
Expand Down Expand Up @@ -288,7 +287,7 @@ sysc_sigpending:
jno sysc_return
lmg %r2,%r7,__PT_R2(%r11) # load svc arguments
lghi %r8,0 # svc 0 returns -ENOSYS
lh %r1,__PT_SVC_CODE+2(%r11) # load new svc number
lh %r1,__PT_INT_CODE+2(%r11) # load new svc number
cghi %r1,NR_syscalls
jnl sysc_nr_ok # invalid svc number -> do svc 0
slag %r8,%r1,2
Expand Down Expand Up @@ -318,7 +317,7 @@ sysc_singlestep:
sysc_tracesys:
lgr %r2,%r11 # pass pointer to pt_regs
la %r3,0
llgh %r0,__PT_SVC_CODE+2(%r11)
llgh %r0,__PT_INT_CODE+2(%r11)
stg %r0,__PT_R2(%r11)
brasl %r14,do_syscall_trace_enter
lghi %r0,NR_syscalls
Expand Down Expand Up @@ -411,6 +410,8 @@ ENTRY(pgm_check_handler)
stmg %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
stmg %r8,%r9,__PT_PSW(%r11)
mvc __PT_INT_CODE(4,%r11),__LC_PGM_ILC
mvc __PT_INT_PARM_LONG(8,%r11),__LC_TRANS_EXC_CODE
stg %r10,__PT_ARGS(%r11)
tm __LC_PGM_ILC+3,0x80 # check for per exception
jz 0f
Expand All @@ -421,15 +422,13 @@ ENTRY(pgm_check_handler)
mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS
mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE
mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID
0: lgf %r3,__LC_PGM_ILC # load program interruption code
lg %r4,__LC_TRANS_EXC_CODE
REENABLE_IRQS
0: REENABLE_IRQS
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
lghi %r10,0x7f
ngr %r10,%r3
je sysc_return
sll %r10,3
larl %r1,pgm_check_table
llgh %r10,__PT_INT_CODE+2(%r11)
nill %r10,0x007f
sll %r10,3
je sysc_return
lg %r1,0(%r10,%r1) # load address of handler routine
lgr %r2,%r11 # pass pointer to pt_regs
basr %r14,%r1 # branch to interrupt-handler
Expand Down Expand Up @@ -877,7 +876,7 @@ cleanup_system_call:
mvc __PT_R8(64,%r15),__LC_SAVE_AREA_SYNC
stmg %r0,%r7,__PT_R0(%r15)
mvc __PT_PSW(16,%r15),__LC_SVC_OLD_PSW
mvc __PT_SVC_CODE(4,%r15),__LC_SVC_ILC
mvc __PT_INT_CODE(4,%r15),__LC_SVC_ILC
# setup saved register r15
aghi %r15,-STACK_FRAME_OVERHEAD
stg %r15,56(%r11) # r15 stack pointer
Expand Down
20 changes: 12 additions & 8 deletions arch/s390/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,13 @@ static int setup_frame(int sig, struct k_sigaction *ka,

/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility, they are passed as args. */
regs->gprs[4] = current->thread.trap_no;
regs->gprs[5] = current->thread.prot_addr;
regs->gprs[6] = task_thread_info(current)->last_break;
if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
sig == SIGTRAP || sig == SIGFPE) {
/* set extra registers only for synchronous signals */
regs->gprs[4] = regs->int_code & 127;
regs->gprs[5] = regs->int_parm_long;
regs->gprs[6] = task_thread_info(current)->last_break;
}

/* Place signal number on stack to allow backtrace from handler. */
if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
Expand Down Expand Up @@ -434,13 +438,13 @@ void do_signal(struct pt_regs *regs)
* call information.
*/
current_thread_info()->system_call =
test_thread_flag(TIF_SYSCALL) ? regs->svc_code : 0;
test_thread_flag(TIF_SYSCALL) ? regs->int_code : 0;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);

if (signr > 0) {
/* Whee! Actually deliver the signal. */
if (current_thread_info()->system_call) {
regs->svc_code = current_thread_info()->system_call;
regs->int_code = current_thread_info()->system_call;
/* Check for system call restarting. */
switch (regs->gprs[2]) {
case -ERESTART_RESTARTBLOCK:
Expand All @@ -457,7 +461,7 @@ void do_signal(struct pt_regs *regs)
regs->gprs[2] = regs->orig_gpr2;
regs->psw.addr =
__rewind_psw(regs->psw,
regs->svc_code >> 16);
regs->int_code >> 16);
break;
}
}
Expand Down Expand Up @@ -488,11 +492,11 @@ void do_signal(struct pt_regs *regs)
/* No handlers present - check for system call restart */
clear_thread_flag(TIF_SYSCALL);
if (current_thread_info()->system_call) {
regs->svc_code = current_thread_info()->system_call;
regs->int_code = current_thread_info()->system_call;
switch (regs->gprs[2]) {
case -ERESTART_RESTARTBLOCK:
/* Restart with sys_restart_syscall */
regs->svc_code = __NR_restart_syscall;
regs->int_code = __NR_restart_syscall;
/* fallthrough */
case -ERESTARTNOHAND:
case -ERESTARTSYS:
Expand Down
Loading

0 comments on commit aa33c8c

Please sign in to comment.