aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/kdebug.h2
-rw-r--r--arch/s390/include/asm/processor.h2
-rw-r--r--arch/s390/include/asm/ptrace.h3
-rw-r--r--arch/s390/include/asm/syscall.h2
-rw-r--r--arch/s390/kernel/asm-offsets.c3
-rw-r--r--arch/s390/kernel/compat_signal.c8
-rw-r--r--arch/s390/kernel/entry.S22
-rw-r--r--arch/s390/kernel/entry.h10
-rw-r--r--arch/s390/kernel/entry64.S27
-rw-r--r--arch/s390/kernel/signal.c20
-rw-r--r--arch/s390/kernel/traps.c168
-rw-r--r--arch/s390/mm/fault.c101
12 files changed, 158 insertions, 210 deletions
diff --git a/arch/s390/include/asm/kdebug.h b/arch/s390/include/asm/kdebug.h
index 40db27cd6e60..5c1abd47612a 100644
--- a/arch/s390/include/asm/kdebug.h
+++ b/arch/s390/include/asm/kdebug.h
@@ -22,6 +22,6 @@ enum die_val {
22 DIE_NMI_IPI, 22 DIE_NMI_IPI,
23}; 23};
24 24
25extern void die(const char *, struct pt_regs *, long); 25extern void die(struct pt_regs *, const char *);
26 26
27#endif 27#endif
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 5f33d37d032c..27272f6a14c2 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -80,8 +80,6 @@ struct thread_struct {
80 unsigned int acrs[NUM_ACRS]; 80 unsigned int acrs[NUM_ACRS];
81 unsigned long ksp; /* kernel stack pointer */ 81 unsigned long ksp; /* kernel stack pointer */
82 mm_segment_t mm_segment; 82 mm_segment_t mm_segment;
83 unsigned long prot_addr; /* address of protection-excep. */
84 unsigned int trap_no;
85 unsigned long gmap_addr; /* address of last gmap fault. */ 83 unsigned long gmap_addr; /* address of last gmap fault. */
86 struct per_regs per_user; /* User specified PER registers */ 84 struct per_regs per_user; /* User specified PER registers */
87 struct per_event per_event; /* Cause of the last PER trap */ 85 struct per_event per_event; /* Cause of the last PER trap */
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index a65846340d51..56da355678f4 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -324,7 +324,8 @@ struct pt_regs
324 psw_t psw; 324 psw_t psw;
325 unsigned long gprs[NUM_GPRS]; 325 unsigned long gprs[NUM_GPRS];
326 unsigned long orig_gpr2; 326 unsigned long orig_gpr2;
327 unsigned int svc_code; 327 unsigned int int_code;
328 unsigned long int_parm_long;
328}; 329};
329 330
330/* 331/*
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index b239ff53b189..fb214dd9b7e0 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -27,7 +27,7 @@ static inline long syscall_get_nr(struct task_struct *task,
27 struct pt_regs *regs) 27 struct pt_regs *regs)
28{ 28{
29 return test_tsk_thread_flag(task, TIF_SYSCALL) ? 29 return test_tsk_thread_flag(task, TIF_SYSCALL) ?
30 (regs->svc_code & 0xffff) : -1; 30 (regs->int_code & 0xffff) : -1;
31} 31}
32 32
33static inline void syscall_rollback(struct task_struct *task, 33static inline void syscall_rollback(struct task_struct *task,
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index c1a56ba5f848..6e6a72e66d60 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -45,7 +45,8 @@ int main(void)
45 DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); 45 DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
46 DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs)); 46 DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs));
47 DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2)); 47 DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2));
48 DEFINE(__PT_SVC_CODE, offsetof(struct pt_regs, svc_code)); 48 DEFINE(__PT_INT_CODE, offsetof(struct pt_regs, int_code));
49 DEFINE(__PT_INT_PARM_LONG, offsetof(struct pt_regs, int_parm_long));
49 DEFINE(__PT_SIZE, sizeof(struct pt_regs)); 50 DEFINE(__PT_SIZE, sizeof(struct pt_regs));
50 BLANK(); 51 BLANK();
51 DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain)); 52 DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 4f68c81d3ffa..60c268b16f91 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -501,8 +501,12 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
501 501
502 /* We forgot to include these in the sigcontext. 502 /* We forgot to include these in the sigcontext.
503 To avoid breaking binary compatibility, they are passed as args. */ 503 To avoid breaking binary compatibility, they are passed as args. */
504 regs->gprs[4] = current->thread.trap_no; 504 if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
505 regs->gprs[5] = current->thread.prot_addr; 505 sig == SIGTRAP || sig == SIGFPE) {
506 /* set extra registers only for synchronous signals */
507 regs->gprs[4] = regs->int_code & 127;
508 regs->gprs[5] = regs->int_parm_long;
509 }
506 510
507 /* Place signal number on stack to allow backtrace from handler. */ 511 /* Place signal number on stack to allow backtrace from handler. */
508 if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo)) 512 if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index c2773cff89c3..3705700ed374 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -184,16 +184,16 @@ sysc_vtime:
184 stm %r0,%r7,__PT_R0(%r11) 184 stm %r0,%r7,__PT_R0(%r11)
185 mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC 185 mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC
186 mvc __PT_PSW(8,%r11),__LC_SVC_OLD_PSW 186 mvc __PT_PSW(8,%r11),__LC_SVC_OLD_PSW
187 mvc __PT_SVC_CODE(4,%r11),__LC_SVC_ILC 187 mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
188sysc_do_svc: 188sysc_do_svc:
189 oi __TI_flags+3(%r12),_TIF_SYSCALL 189 oi __TI_flags+3(%r12),_TIF_SYSCALL
190 lh %r8,__PT_SVC_CODE+2(%r11) 190 lh %r8,__PT_INT_CODE+2(%r11)
191 sla %r8,2 # shift and test for svc0 191 sla %r8,2 # shift and test for svc0
192 jnz sysc_nr_ok 192 jnz sysc_nr_ok
193 # svc 0: system call number in %r1 193 # svc 0: system call number in %r1
194 cl %r1,BASED(.Lnr_syscalls) 194 cl %r1,BASED(.Lnr_syscalls)
195 jnl sysc_nr_ok 195 jnl sysc_nr_ok
196 sth %r1,__PT_SVC_CODE+2(%r11) 196 sth %r1,__PT_INT_CODE+2(%r11)
197 lr %r8,%r1 197 lr %r8,%r1
198 sla %r8,2 198 sla %r8,2
199sysc_nr_ok: 199sysc_nr_ok:
@@ -266,9 +266,9 @@ sysc_sigpending:
266 jno sysc_return 266 jno sysc_return
267 lm %r2,%r7,__PT_R2(%r11) # load svc arguments 267 lm %r2,%r7,__PT_R2(%r11) # load svc arguments
268 xr %r8,%r8 # svc 0 returns -ENOSYS 268 xr %r8,%r8 # svc 0 returns -ENOSYS
269 clc __PT_SVC_CODE+2(2,%r11),BASED(.Lnr_syscalls+2) 269 clc __PT_INT_CODE+2(2,%r11),BASED(.Lnr_syscalls+2)
270 jnl sysc_nr_ok # invalid svc number -> do svc 0 270 jnl sysc_nr_ok # invalid svc number -> do svc 0
271 lh %r8,__PT_SVC_CODE+2(%r11) # load new svc number 271 lh %r8,__PT_INT_CODE+2(%r11) # load new svc number
272 sla %r8,2 272 sla %r8,2
273 j sysc_nr_ok # restart svc 273 j sysc_nr_ok # restart svc
274 274
@@ -300,7 +300,7 @@ sysc_tracesys:
300 lr %r2,%r11 # pass pointer to pt_regs 300 lr %r2,%r11 # pass pointer to pt_regs
301 la %r3,0 301 la %r3,0
302 xr %r0,%r0 302 xr %r0,%r0
303 icm %r0,3,__PT_SVC_CODE+2(%r11) 303 icm %r0,3,__PT_INT_CODE+2(%r11)
304 st %r0,__PT_R2(%r11) 304 st %r0,__PT_R2(%r11)
305 basr %r14,%r1 # call do_syscall_trace_enter 305 basr %r14,%r1 # call do_syscall_trace_enter
306 cl %r2,BASED(.Lnr_syscalls) 306 cl %r2,BASED(.Lnr_syscalls)
@@ -396,6 +396,8 @@ ENTRY(pgm_check_handler)
396 stm %r0,%r7,__PT_R0(%r11) 396 stm %r0,%r7,__PT_R0(%r11)
397 mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC 397 mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC
398 stm %r8,%r9,__PT_PSW(%r11) 398 stm %r8,%r9,__PT_PSW(%r11)
399 mvc __PT_INT_CODE(4,%r11),__LC_PGM_ILC
400 mvc __PT_INT_PARM_LONG(4,%r11),__LC_TRANS_EXC_CODE
399 tm __LC_PGM_ILC+3,0x80 # check for per exception 401 tm __LC_PGM_ILC+3,0x80 # check for per exception
400 jz 0f 402 jz 0f
401 l %r1,__TI_task(%r12) 403 l %r1,__TI_task(%r12)
@@ -405,13 +407,11 @@ ENTRY(pgm_check_handler)
405 mvc __THREAD_per_address(4,%r1),__LC_PER_ADDRESS 407 mvc __THREAD_per_address(4,%r1),__LC_PER_ADDRESS
406 mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE 408 mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE
407 mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID 409 mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID
4080: l %r3,__LC_PGM_ILC # load program interruption code 4100: REENABLE_IRQS
409 l %r4,__LC_TRANS_EXC_CODE
410 REENABLE_IRQS
411 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 411 xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
412 l %r1,BASED(.Ljump_table) 412 l %r1,BASED(.Ljump_table)
413 la %r10,0x7f 413 la %r10,0x7f
414 nr %r10,%r3 414 n %r10,__PT_INT_CODE(%r11)
415 je sysc_return 415 je sysc_return
416 sll %r10,2 416 sll %r10,2
417 l %r1,0(%r10,%r1) # load address of handler routine 417 l %r1,0(%r10,%r1) # load address of handler routine
@@ -858,7 +858,7 @@ cleanup_system_call:
858 mvc __PT_R8(32,%r15),__LC_SAVE_AREA_SYNC 858 mvc __PT_R8(32,%r15),__LC_SAVE_AREA_SYNC
859 stm %r0,%r7,__PT_R0(%r15) 859 stm %r0,%r7,__PT_R0(%r15)
860 mvc __PT_PSW(8,%r15),__LC_SVC_OLD_PSW 860 mvc __PT_PSW(8,%r15),__LC_SVC_OLD_PSW
861 mvc __PT_SVC_CODE(4,%r15),__LC_SVC_ILC 861 mvc __PT_INT_CODE(4,%r15),__LC_SVC_ILC
862 # setup saved register 15 862 # setup saved register 15
863 ahi %r15,-STACK_FRAME_OVERHEAD 863 ahi %r15,-STACK_FRAME_OVERHEAD
864 st %r15,28(%r11) # r15 stack pointer 864 st %r15,28(%r11) # r15 stack pointer
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index ef8fb1d6e8d7..bf538aaf407d 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -6,15 +6,15 @@
6#include <asm/ptrace.h> 6#include <asm/ptrace.h>
7 7
8 8
9extern void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long); 9extern void (*pgm_check_table[128])(struct pt_regs *);
10extern void *restart_stack; 10extern void *restart_stack;
11 11
12asmlinkage long do_syscall_trace_enter(struct pt_regs *regs); 12asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
13asmlinkage void do_syscall_trace_exit(struct pt_regs *regs); 13asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
14 14
15void do_protection_exception(struct pt_regs *, long, unsigned long); 15void do_protection_exception(struct pt_regs *regs);
16void do_dat_exception(struct pt_regs *, long, unsigned long); 16void do_dat_exception(struct pt_regs *regs);
17void do_asce_exception(struct pt_regs *, long, unsigned long); 17void do_asce_exception(struct pt_regs *regs);
18 18
19void do_per_trap(struct pt_regs *regs); 19void do_per_trap(struct pt_regs *regs);
20void syscall_trace(struct pt_regs *regs, int entryexit); 20void syscall_trace(struct pt_regs *regs, int entryexit);
@@ -28,7 +28,7 @@ void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long);
28void do_restart(void); 28void do_restart(void);
29int __cpuinit start_secondary(void *cpuvoid); 29int __cpuinit start_secondary(void *cpuvoid);
30void __init startup_init(void); 30void __init startup_init(void);
31void die(const char * str, struct pt_regs * regs, long err); 31void die(struct pt_regs *regs, const char *str);
32 32
33void __init time_init(void); 33void __init time_init(void);
34 34
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 73845a9e587c..412a7b8783d7 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -1,4 +1,3 @@
1
2/* 1/*
3 * arch/s390/kernel/entry64.S 2 * arch/s390/kernel/entry64.S
4 * S390 low-level entry points. 3 * S390 low-level entry points.
@@ -200,17 +199,17 @@ sysc_vtime:
200 stmg %r0,%r7,__PT_R0(%r11) 199 stmg %r0,%r7,__PT_R0(%r11)
201 mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC 200 mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
202 mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW 201 mvc __PT_PSW(16,%r11),__LC_SVC_OLD_PSW
203 mvc __PT_SVC_CODE(4,%r11),__LC_SVC_ILC 202 mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
204sysc_do_svc: 203sysc_do_svc:
205 oi __TI_flags+7(%r12),_TIF_SYSCALL 204 oi __TI_flags+7(%r12),_TIF_SYSCALL
206 llgh %r8,__PT_SVC_CODE+2(%r11) 205 llgh %r8,__PT_INT_CODE+2(%r11)
207 slag %r8,%r8,2 # shift and test for svc 0 206 slag %r8,%r8,2 # shift and test for svc 0
208 jnz sysc_nr_ok 207 jnz sysc_nr_ok
209 # svc 0: system call number in %r1 208 # svc 0: system call number in %r1
210 llgfr %r1,%r1 # clear high word in r1 209 llgfr %r1,%r1 # clear high word in r1
211 cghi %r1,NR_syscalls 210 cghi %r1,NR_syscalls
212 jnl sysc_nr_ok 211 jnl sysc_nr_ok
213 sth %r1,__PT_SVC_CODE+2(%r11) 212 sth %r1,__PT_INT_CODE+2(%r11)
214 slag %r8,%r1,2 213 slag %r8,%r1,2
215sysc_nr_ok: 214sysc_nr_ok:
216 larl %r10,sys_call_table # 64 bit system call table 215 larl %r10,sys_call_table # 64 bit system call table
@@ -288,7 +287,7 @@ sysc_sigpending:
288 jno sysc_return 287 jno sysc_return
289 lmg %r2,%r7,__PT_R2(%r11) # load svc arguments 288 lmg %r2,%r7,__PT_R2(%r11) # load svc arguments
290 lghi %r8,0 # svc 0 returns -ENOSYS 289 lghi %r8,0 # svc 0 returns -ENOSYS
291 lh %r1,__PT_SVC_CODE+2(%r11) # load new svc number 290 lh %r1,__PT_INT_CODE+2(%r11) # load new svc number
292 cghi %r1,NR_syscalls 291 cghi %r1,NR_syscalls
293 jnl sysc_nr_ok # invalid svc number -> do svc 0 292 jnl sysc_nr_ok # invalid svc number -> do svc 0
294 slag %r8,%r1,2 293 slag %r8,%r1,2
@@ -318,7 +317,7 @@ sysc_singlestep:
318sysc_tracesys: 317sysc_tracesys:
319 lgr %r2,%r11 # pass pointer to pt_regs 318 lgr %r2,%r11 # pass pointer to pt_regs
320 la %r3,0 319 la %r3,0
321 llgh %r0,__PT_SVC_CODE+2(%r11) 320 llgh %r0,__PT_INT_CODE+2(%r11)
322 stg %r0,__PT_R2(%r11) 321 stg %r0,__PT_R2(%r11)
323 brasl %r14,do_syscall_trace_enter 322 brasl %r14,do_syscall_trace_enter
324 lghi %r0,NR_syscalls 323 lghi %r0,NR_syscalls
@@ -411,6 +410,8 @@ ENTRY(pgm_check_handler)
411 stmg %r0,%r7,__PT_R0(%r11) 410 stmg %r0,%r7,__PT_R0(%r11)
412 mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC 411 mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
413 stmg %r8,%r9,__PT_PSW(%r11) 412 stmg %r8,%r9,__PT_PSW(%r11)
413 mvc __PT_INT_CODE(4,%r11),__LC_PGM_ILC
414 mvc __PT_INT_PARM_LONG(8,%r11),__LC_TRANS_EXC_CODE
414 stg %r10,__PT_ARGS(%r11) 415 stg %r10,__PT_ARGS(%r11)
415 tm __LC_PGM_ILC+3,0x80 # check for per exception 416 tm __LC_PGM_ILC+3,0x80 # check for per exception
416 jz 0f 417 jz 0f
@@ -421,15 +422,13 @@ ENTRY(pgm_check_handler)
421 mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS 422 mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS
422 mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE 423 mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE
423 mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID 424 mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID
4240: lgf %r3,__LC_PGM_ILC # load program interruption code 4250: REENABLE_IRQS
425 lg %r4,__LC_TRANS_EXC_CODE
426 REENABLE_IRQS
427 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 426 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
428 lghi %r10,0x7f
429 ngr %r10,%r3
430 je sysc_return
431 sll %r10,3
432 larl %r1,pgm_check_table 427 larl %r1,pgm_check_table
428 llgh %r10,__PT_INT_CODE+2(%r11)
429 nill %r10,0x007f
430 sll %r10,3
431 je sysc_return
433 lg %r1,0(%r10,%r1) # load address of handler routine 432 lg %r1,0(%r10,%r1) # load address of handler routine
434 lgr %r2,%r11 # pass pointer to pt_regs 433 lgr %r2,%r11 # pass pointer to pt_regs
435 basr %r14,%r1 # branch to interrupt-handler 434 basr %r14,%r1 # branch to interrupt-handler
@@ -877,7 +876,7 @@ cleanup_system_call:
877 mvc __PT_R8(64,%r15),__LC_SAVE_AREA_SYNC 876 mvc __PT_R8(64,%r15),__LC_SAVE_AREA_SYNC
878 stmg %r0,%r7,__PT_R0(%r15) 877 stmg %r0,%r7,__PT_R0(%r15)
879 mvc __PT_PSW(16,%r15),__LC_SVC_OLD_PSW 878 mvc __PT_PSW(16,%r15),__LC_SVC_OLD_PSW
880 mvc __PT_SVC_CODE(4,%r15),__LC_SVC_ILC 879 mvc __PT_INT_CODE(4,%r15),__LC_SVC_ILC
881 # setup saved register r15 880 # setup saved register r15
882 aghi %r15,-STACK_FRAME_OVERHEAD 881 aghi %r15,-STACK_FRAME_OVERHEAD
883 stg %r15,56(%r11) # r15 stack pointer 882 stg %r15,56(%r11) # r15 stack pointer
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 7f6f9f354545..a8ba840294ff 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -302,9 +302,13 @@ static int setup_frame(int sig, struct k_sigaction *ka,
302 302
303 /* We forgot to include these in the sigcontext. 303 /* We forgot to include these in the sigcontext.
304 To avoid breaking binary compatibility, they are passed as args. */ 304 To avoid breaking binary compatibility, they are passed as args. */
305 regs->gprs[4] = current->thread.trap_no; 305 if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
306 regs->gprs[5] = current->thread.prot_addr; 306 sig == SIGTRAP || sig == SIGFPE) {
307 regs->gprs[6] = task_thread_info(current)->last_break; 307 /* set extra registers only for synchronous signals */
308 regs->gprs[4] = regs->int_code & 127;
309 regs->gprs[5] = regs->int_parm_long;
310 regs->gprs[6] = task_thread_info(current)->last_break;
311 }
308 312
309 /* Place signal number on stack to allow backtrace from handler. */ 313 /* Place signal number on stack to allow backtrace from handler. */
310 if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) 314 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
@@ -434,13 +438,13 @@ void do_signal(struct pt_regs *regs)
434 * call information. 438 * call information.
435 */ 439 */
436 current_thread_info()->system_call = 440 current_thread_info()->system_call =
437 test_thread_flag(TIF_SYSCALL) ? regs->svc_code : 0; 441 test_thread_flag(TIF_SYSCALL) ? regs->int_code : 0;
438 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 442 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
439 443
440 if (signr > 0) { 444 if (signr > 0) {
441 /* Whee! Actually deliver the signal. */ 445 /* Whee! Actually deliver the signal. */
442 if (current_thread_info()->system_call) { 446 if (current_thread_info()->system_call) {
443 regs->svc_code = current_thread_info()->system_call; 447 regs->int_code = current_thread_info()->system_call;
444 /* Check for system call restarting. */ 448 /* Check for system call restarting. */
445 switch (regs->gprs[2]) { 449 switch (regs->gprs[2]) {
446 case -ERESTART_RESTARTBLOCK: 450 case -ERESTART_RESTARTBLOCK:
@@ -457,7 +461,7 @@ void do_signal(struct pt_regs *regs)
457 regs->gprs[2] = regs->orig_gpr2; 461 regs->gprs[2] = regs->orig_gpr2;
458 regs->psw.addr = 462 regs->psw.addr =
459 __rewind_psw(regs->psw, 463 __rewind_psw(regs->psw,
460 regs->svc_code >> 16); 464 regs->int_code >> 16);
461 break; 465 break;
462 } 466 }
463 } 467 }
@@ -488,11 +492,11 @@ void do_signal(struct pt_regs *regs)
488 /* No handlers present - check for system call restart */ 492 /* No handlers present - check for system call restart */
489 clear_thread_flag(TIF_SYSCALL); 493 clear_thread_flag(TIF_SYSCALL);
490 if (current_thread_info()->system_call) { 494 if (current_thread_info()->system_call) {
491 regs->svc_code = current_thread_info()->system_call; 495 regs->int_code = current_thread_info()->system_call;
492 switch (regs->gprs[2]) { 496 switch (regs->gprs[2]) {
493 case -ERESTART_RESTARTBLOCK: 497 case -ERESTART_RESTARTBLOCK:
494 /* Restart with sys_restart_syscall */ 498 /* Restart with sys_restart_syscall */
495 regs->svc_code = __NR_restart_syscall; 499 regs->int_code = __NR_restart_syscall;
496 /* fallthrough */ 500 /* fallthrough */
497 case -ERESTARTNOHAND: 501 case -ERESTARTNOHAND:
498 case -ERESTARTSYS: 502 case -ERESTARTSYS:
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index a9807dd86276..dc6cc1b0ae66 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -43,7 +43,7 @@
43#include <asm/debug.h> 43#include <asm/debug.h>
44#include "entry.h" 44#include "entry.h"
45 45
46void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long); 46void (*pgm_check_table[128])(struct pt_regs *regs);
47 47
48int show_unhandled_signals; 48int show_unhandled_signals;
49 49
@@ -234,7 +234,7 @@ void show_regs(struct pt_regs *regs)
234 234
235static DEFINE_SPINLOCK(die_lock); 235static DEFINE_SPINLOCK(die_lock);
236 236
237void die(const char * str, struct pt_regs * regs, long err) 237void die(struct pt_regs *regs, const char *str)
238{ 238{
239 static int die_counter; 239 static int die_counter;
240 240
@@ -243,7 +243,7 @@ void die(const char * str, struct pt_regs * regs, long err)
243 console_verbose(); 243 console_verbose();
244 spin_lock_irq(&die_lock); 244 spin_lock_irq(&die_lock);
245 bust_spinlocks(1); 245 bust_spinlocks(1);
246 printk("%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); 246 printk("%s: %04x [#%d] ", str, regs->int_code & 0xffff, ++die_counter);
247#ifdef CONFIG_PREEMPT 247#ifdef CONFIG_PREEMPT
248 printk("PREEMPT "); 248 printk("PREEMPT ");
249#endif 249#endif
@@ -254,7 +254,7 @@ void die(const char * str, struct pt_regs * regs, long err)
254 printk("DEBUG_PAGEALLOC"); 254 printk("DEBUG_PAGEALLOC");
255#endif 255#endif
256 printk("\n"); 256 printk("\n");
257 notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV); 257 notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
258 show_regs(regs); 258 show_regs(regs);
259 bust_spinlocks(0); 259 bust_spinlocks(0);
260 add_taint(TAINT_DIE); 260 add_taint(TAINT_DIE);
@@ -267,8 +267,7 @@ void die(const char * str, struct pt_regs * regs, long err)
267 do_exit(SIGSEGV); 267 do_exit(SIGSEGV);
268} 268}
269 269
270static void inline report_user_fault(struct pt_regs *regs, long int_code, 270static inline void report_user_fault(struct pt_regs *regs, int signr)
271 int signr)
272{ 271{
273 if ((task_pid_nr(current) > 1) && !show_unhandled_signals) 272 if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
274 return; 273 return;
@@ -276,7 +275,7 @@ static void inline report_user_fault(struct pt_regs *regs, long int_code,
276 return; 275 return;
277 if (!printk_ratelimit()) 276 if (!printk_ratelimit())
278 return; 277 return;
279 printk("User process fault: interruption code 0x%lX ", int_code); 278 printk("User process fault: interruption code 0x%X ", regs->int_code);
280 print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN); 279 print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN);
281 printk("\n"); 280 printk("\n");
282 show_regs(regs); 281 show_regs(regs);
@@ -287,19 +286,28 @@ int is_valid_bugaddr(unsigned long addr)
287 return 1; 286 return 1;
288} 287}
289 288
290static inline void __kprobes do_trap(long pgm_int_code, int signr, char *str, 289static inline void __user *get_psw_address(struct pt_regs *regs)
291 struct pt_regs *regs, siginfo_t *info)
292{ 290{
293 if (notify_die(DIE_TRAP, str, regs, pgm_int_code, 291 return (void __user *)
294 pgm_int_code, signr) == NOTIFY_STOP) 292 ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN);
293}
294
295static void __kprobes do_trap(struct pt_regs *regs,
296 int si_signo, int si_code, char *str)
297{
298 siginfo_t info;
299
300 if (notify_die(DIE_TRAP, str, regs, 0,
301 regs->int_code, si_signo) == NOTIFY_STOP)
295 return; 302 return;
296 303
297 if (regs->psw.mask & PSW_MASK_PSTATE) { 304 if (regs->psw.mask & PSW_MASK_PSTATE) {
298 struct task_struct *tsk = current; 305 info.si_signo = si_signo;
299 306 info.si_errno = 0;
300 tsk->thread.trap_no = pgm_int_code & 0xffff; 307 info.si_code = si_code;
301 force_sig_info(signr, info, tsk); 308 info.si_addr = get_psw_address(regs);
302 report_user_fault(regs, pgm_int_code, signr); 309 force_sig_info(si_signo, &info, current);
310 report_user_fault(regs, si_signo);
303 } else { 311 } else {
304 const struct exception_table_entry *fixup; 312 const struct exception_table_entry *fixup;
305 fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); 313 fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
@@ -311,18 +319,11 @@ static inline void __kprobes do_trap(long pgm_int_code, int signr, char *str,
311 btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs); 319 btt = report_bug(regs->psw.addr & PSW_ADDR_INSN, regs);
312 if (btt == BUG_TRAP_TYPE_WARN) 320 if (btt == BUG_TRAP_TYPE_WARN)
313 return; 321 return;
314 die(str, regs, pgm_int_code); 322 die(regs, str);
315 } 323 }
316 } 324 }
317} 325}
318 326
319static inline void __user *get_psw_address(struct pt_regs *regs,
320 long pgm_int_code)
321{
322 return (void __user *)
323 ((regs->psw.addr - (pgm_int_code >> 16)) & PSW_ADDR_INSN);
324}
325
326void __kprobes do_per_trap(struct pt_regs *regs) 327void __kprobes do_per_trap(struct pt_regs *regs)
327{ 328{
328 siginfo_t info; 329 siginfo_t info;
@@ -339,26 +340,19 @@ void __kprobes do_per_trap(struct pt_regs *regs)
339 force_sig_info(SIGTRAP, &info, current); 340 force_sig_info(SIGTRAP, &info, current);
340} 341}
341 342
342static void default_trap_handler(struct pt_regs *regs, long pgm_int_code, 343static void default_trap_handler(struct pt_regs *regs)
343 unsigned long trans_exc_code)
344{ 344{
345 if (regs->psw.mask & PSW_MASK_PSTATE) { 345 if (regs->psw.mask & PSW_MASK_PSTATE) {
346 report_user_fault(regs, pgm_int_code, SIGSEGV); 346 report_user_fault(regs, SIGSEGV);
347 do_exit(SIGSEGV); 347 do_exit(SIGSEGV);
348 } else 348 } else
349 die("Unknown program exception", regs, pgm_int_code); 349 die(regs, "Unknown program exception");
350} 350}
351 351
352#define DO_ERROR_INFO(name, signr, sicode, str) \ 352#define DO_ERROR_INFO(name, signr, sicode, str) \
353static void name(struct pt_regs *regs, long pgm_int_code, \ 353static void name(struct pt_regs *regs) \
354 unsigned long trans_exc_code) \
355{ \ 354{ \
356 siginfo_t info; \ 355 do_trap(regs, signr, sicode, str); \
357 info.si_signo = signr; \
358 info.si_errno = 0; \
359 info.si_code = sicode; \
360 info.si_addr = get_psw_address(regs, pgm_int_code); \
361 do_trap(pgm_int_code, signr, str, regs, &info); \
362} 356}
363 357
364DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR, 358DO_ERROR_INFO(addressing_exception, SIGILL, ILL_ILLADR,
@@ -388,42 +382,34 @@ DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN,
388DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, 382DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN,
389 "translation exception") 383 "translation exception")
390 384
391static inline void do_fp_trap(struct pt_regs *regs, void __user *location, 385static inline void do_fp_trap(struct pt_regs *regs, int fpc)
392 int fpc, long pgm_int_code)
393{ 386{
394 siginfo_t si; 387 int si_code = 0;
395
396 si.si_signo = SIGFPE;
397 si.si_errno = 0;
398 si.si_addr = location;
399 si.si_code = 0;
400 /* FPC[2] is Data Exception Code */ 388 /* FPC[2] is Data Exception Code */
401 if ((fpc & 0x00000300) == 0) { 389 if ((fpc & 0x00000300) == 0) {
402 /* bits 6 and 7 of DXC are 0 iff IEEE exception */ 390 /* bits 6 and 7 of DXC are 0 iff IEEE exception */
403 if (fpc & 0x8000) /* invalid fp operation */ 391 if (fpc & 0x8000) /* invalid fp operation */
404 si.si_code = FPE_FLTINV; 392 si_code = FPE_FLTINV;
405 else if (fpc & 0x4000) /* div by 0 */ 393 else if (fpc & 0x4000) /* div by 0 */
406 si.si_code = FPE_FLTDIV; 394 si_code = FPE_FLTDIV;
407 else if (fpc & 0x2000) /* overflow */ 395 else if (fpc & 0x2000) /* overflow */
408 si.si_code = FPE_FLTOVF; 396 si_code = FPE_FLTOVF;
409 else if (fpc & 0x1000) /* underflow */ 397 else if (fpc & 0x1000) /* underflow */
410 si.si_code = FPE_FLTUND; 398 si_code = FPE_FLTUND;
411 else if (fpc & 0x0800) /* inexact */ 399 else if (fpc & 0x0800) /* inexact */
412 si.si_code = FPE_FLTRES; 400 si_code = FPE_FLTRES;
413 } 401 }
414 do_trap(pgm_int_code, SIGFPE, 402 do_trap(regs, SIGFPE, si_code, "floating point exception");
415 "floating point exception", regs, &si);
416} 403}
417 404
418static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code, 405static void __kprobes illegal_op(struct pt_regs *regs)
419 unsigned long trans_exc_code)
420{ 406{
421 siginfo_t info; 407 siginfo_t info;
422 __u8 opcode[6]; 408 __u8 opcode[6];
423 __u16 __user *location; 409 __u16 __user *location;
424 int signal = 0; 410 int signal = 0;
425 411
426 location = get_psw_address(regs, pgm_int_code); 412 location = get_psw_address(regs);
427 413
428 if (regs->psw.mask & PSW_MASK_PSTATE) { 414 if (regs->psw.mask & PSW_MASK_PSTATE) {
429 if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) 415 if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
@@ -467,44 +453,31 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
467 * If we get an illegal op in kernel mode, send it through the 453 * If we get an illegal op in kernel mode, send it through the
468 * kprobes notifier. If kprobes doesn't pick it up, SIGILL 454 * kprobes notifier. If kprobes doesn't pick it up, SIGILL
469 */ 455 */
470 if (notify_die(DIE_BPT, "bpt", regs, pgm_int_code, 456 if (notify_die(DIE_BPT, "bpt", regs, 0,
471 3, SIGTRAP) != NOTIFY_STOP) 457 3, SIGTRAP) != NOTIFY_STOP)
472 signal = SIGILL; 458 signal = SIGILL;
473 } 459 }
474 460
475#ifdef CONFIG_MATHEMU 461#ifdef CONFIG_MATHEMU
476 if (signal == SIGFPE) 462 if (signal == SIGFPE)
477 do_fp_trap(regs, location, 463 do_fp_trap(regs, current->thread.fp_regs.fpc);
478 current->thread.fp_regs.fpc, pgm_int_code); 464 else if (signal == SIGSEGV)
479 else if (signal == SIGSEGV) { 465 do_trap(regs, signal, SEGV_MAPERR, "user address fault");
480 info.si_signo = signal; 466 else
481 info.si_errno = 0;
482 info.si_code = SEGV_MAPERR;
483 info.si_addr = (void __user *) location;
484 do_trap(pgm_int_code, signal,
485 "user address fault", regs, &info);
486 } else
487#endif 467#endif
488 if (signal) { 468 if (signal)
489 info.si_signo = signal; 469 do_trap(regs, signal, ILL_ILLOPC, "illegal operation");
490 info.si_errno = 0;
491 info.si_code = ILL_ILLOPC;
492 info.si_addr = (void __user *) location;
493 do_trap(pgm_int_code, signal,
494 "illegal operation", regs, &info);
495 }
496} 470}
497 471
498 472
499#ifdef CONFIG_MATHEMU 473#ifdef CONFIG_MATHEMU
500void specification_exception(struct pt_regs *regs, long pgm_int_code, 474void specification_exception(struct pt_regs *regs)
501 unsigned long trans_exc_code)
502{ 475{
503 __u8 opcode[6]; 476 __u8 opcode[6];
504 __u16 __user *location = NULL; 477 __u16 __user *location = NULL;
505 int signal = 0; 478 int signal = 0;
506 479
507 location = (__u16 __user *) get_psw_address(regs, pgm_int_code); 480 location = (__u16 __user *) get_psw_address(regs);
508 481
509 if (regs->psw.mask & PSW_MASK_PSTATE) { 482 if (regs->psw.mask & PSW_MASK_PSTATE) {
510 get_user(*((__u16 *) opcode), location); 483 get_user(*((__u16 *) opcode), location);
@@ -539,30 +512,21 @@ void specification_exception(struct pt_regs *regs, long pgm_int_code,
539 signal = SIGILL; 512 signal = SIGILL;
540 513
541 if (signal == SIGFPE) 514 if (signal == SIGFPE)
542 do_fp_trap(regs, location, 515 do_fp_trap(regs, current->thread.fp_regs.fpc);
543 current->thread.fp_regs.fpc, pgm_int_code); 516 else if (signal)
544 else if (signal) { 517 do_trap(regs, signal, ILL_ILLOPN, "specification exception");
545 siginfo_t info;
546 info.si_signo = signal;
547 info.si_errno = 0;
548 info.si_code = ILL_ILLOPN;
549 info.si_addr = location;
550 do_trap(pgm_int_code, signal,
551 "specification exception", regs, &info);
552 }
553} 518}
554#else 519#else
555DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN, 520DO_ERROR_INFO(specification_exception, SIGILL, ILL_ILLOPN,
556 "specification exception"); 521 "specification exception");
557#endif 522#endif
558 523
559static void data_exception(struct pt_regs *regs, long pgm_int_code, 524static void data_exception(struct pt_regs *regs)
560 unsigned long trans_exc_code)
561{ 525{
562 __u16 __user *location; 526 __u16 __user *location;
563 int signal = 0; 527 int signal = 0;
564 528
565 location = get_psw_address(regs, pgm_int_code); 529 location = get_psw_address(regs);
566 530
567 if (MACHINE_HAS_IEEE) 531 if (MACHINE_HAS_IEEE)
568 asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); 532 asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
@@ -627,32 +591,18 @@ static void data_exception(struct pt_regs *regs, long pgm_int_code,
627 else 591 else
628 signal = SIGILL; 592 signal = SIGILL;
629 if (signal == SIGFPE) 593 if (signal == SIGFPE)
630 do_fp_trap(regs, location, 594 do_fp_trap(regs, current->thread.fp_regs.fpc);
631 current->thread.fp_regs.fpc, pgm_int_code); 595 else if (signal)
632 else if (signal) { 596 do_trap(regs, signal, ILL_ILLOPN, "data exception");
633 siginfo_t info;
634 info.si_signo = signal;
635 info.si_errno = 0;
636 info.si_code = ILL_ILLOPN;
637 info.si_addr = location;
638 do_trap(pgm_int_code, signal, "data exception", regs, &info);
639 }
640} 597}
641 598
642static void space_switch_exception(struct pt_regs *regs, long pgm_int_code, 599static void space_switch_exception(struct pt_regs *regs)
643 unsigned long trans_exc_code)
644{ 600{
645 siginfo_t info;
646
647 /* Set user psw back to home space mode. */ 601 /* Set user psw back to home space mode. */
648 if (regs->psw.mask & PSW_MASK_PSTATE) 602 if (regs->psw.mask & PSW_MASK_PSTATE)
649 regs->psw.mask |= PSW_ASC_HOME; 603 regs->psw.mask |= PSW_ASC_HOME;
650 /* Send SIGILL. */ 604 /* Send SIGILL. */
651 info.si_signo = SIGILL; 605 do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
652 info.si_errno = 0;
653 info.si_code = ILL_PRVOPC;
654 info.si_addr = get_psw_address(regs, pgm_int_code);
655 do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info);
656} 606}
657 607
658void __kprobes kernel_stack_overflow(struct pt_regs * regs) 608void __kprobes kernel_stack_overflow(struct pt_regs * regs)
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index a9d3583922ec..354dd39073ef 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -125,8 +125,7 @@ static inline int user_space_fault(unsigned long trans_exc_code)
125 return trans_exc_code != 3; 125 return trans_exc_code != 3;
126} 126}
127 127
128static inline void report_user_fault(struct pt_regs *regs, long int_code, 128static inline void report_user_fault(struct pt_regs *regs, long signr)
129 int signr, unsigned long address)
130{ 129{
131 if ((task_pid_nr(current) > 1) && !show_unhandled_signals) 130 if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
132 return; 131 return;
@@ -134,10 +133,12 @@ static inline void report_user_fault(struct pt_regs *regs, long int_code,
134 return; 133 return;
135 if (!printk_ratelimit()) 134 if (!printk_ratelimit())
136 return; 135 return;
137 printk("User process fault: interruption code 0x%lX ", int_code); 136 printk(KERN_ALERT "User process fault: interruption code 0x%X ",
137 regs->int_code);
138 print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN); 138 print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN);
139 printk("\n"); 139 printk(KERN_CONT "\n");
140 printk("failing address: %lX\n", address); 140 printk(KERN_ALERT "failing address: %lX\n",
141 regs->int_parm_long & __FAIL_ADDR_MASK);
141 show_regs(regs); 142 show_regs(regs);
142} 143}
143 144
@@ -145,24 +146,18 @@ static inline void report_user_fault(struct pt_regs *regs, long int_code,
145 * Send SIGSEGV to task. This is an external routine 146 * Send SIGSEGV to task. This is an external routine
146 * to keep the stack usage of do_page_fault small. 147 * to keep the stack usage of do_page_fault small.
147 */ 148 */
148static noinline void do_sigsegv(struct pt_regs *regs, long int_code, 149static noinline void do_sigsegv(struct pt_regs *regs, int si_code)
149 int si_code, unsigned long trans_exc_code)
150{ 150{
151 struct siginfo si; 151 struct siginfo si;
152 unsigned long address;
153 152
154 address = trans_exc_code & __FAIL_ADDR_MASK; 153 report_user_fault(regs, SIGSEGV);
155 current->thread.prot_addr = address;
156 current->thread.trap_no = int_code;
157 report_user_fault(regs, int_code, SIGSEGV, address);
158 si.si_signo = SIGSEGV; 154 si.si_signo = SIGSEGV;
159 si.si_code = si_code; 155 si.si_code = si_code;
160 si.si_addr = (void __user *) address; 156 si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
161 force_sig_info(SIGSEGV, &si, current); 157 force_sig_info(SIGSEGV, &si, current);
162} 158}
163 159
164static noinline void do_no_context(struct pt_regs *regs, long int_code, 160static noinline void do_no_context(struct pt_regs *regs)
165 unsigned long trans_exc_code)
166{ 161{
167 const struct exception_table_entry *fixup; 162 const struct exception_table_entry *fixup;
168 unsigned long address; 163 unsigned long address;
@@ -178,55 +173,48 @@ static noinline void do_no_context(struct pt_regs *regs, long int_code,
178 * Oops. The kernel tried to access some bad page. We'll have to 173 * Oops. The kernel tried to access some bad page. We'll have to
179 * terminate things with extreme prejudice. 174 * terminate things with extreme prejudice.
180 */ 175 */
181 address = trans_exc_code & __FAIL_ADDR_MASK; 176 address = regs->int_parm_long & __FAIL_ADDR_MASK;
182 if (!user_space_fault(trans_exc_code)) 177 if (!user_space_fault(regs->int_parm_long))
183 printk(KERN_ALERT "Unable to handle kernel pointer dereference" 178 printk(KERN_ALERT "Unable to handle kernel pointer dereference"
184 " at virtual kernel address %p\n", (void *)address); 179 " at virtual kernel address %p\n", (void *)address);
185 else 180 else
186 printk(KERN_ALERT "Unable to handle kernel paging request" 181 printk(KERN_ALERT "Unable to handle kernel paging request"
187 " at virtual user address %p\n", (void *)address); 182 " at virtual user address %p\n", (void *)address);
188 183
189 die("Oops", regs, int_code); 184 die(regs, "Oops");
190 do_exit(SIGKILL); 185 do_exit(SIGKILL);
191} 186}
192 187
193static noinline void do_low_address(struct pt_regs *regs, long int_code, 188static noinline void do_low_address(struct pt_regs *regs)
194 unsigned long trans_exc_code)
195{ 189{
196 /* Low-address protection hit in kernel mode means 190 /* Low-address protection hit in kernel mode means
197 NULL pointer write access in kernel mode. */ 191 NULL pointer write access in kernel mode. */
198 if (regs->psw.mask & PSW_MASK_PSTATE) { 192 if (regs->psw.mask & PSW_MASK_PSTATE) {
199 /* Low-address protection hit in user mode 'cannot happen'. */ 193 /* Low-address protection hit in user mode 'cannot happen'. */
200 die ("Low-address protection", regs, int_code); 194 die (regs, "Low-address protection");
201 do_exit(SIGKILL); 195 do_exit(SIGKILL);
202 } 196 }
203 197
204 do_no_context(regs, int_code, trans_exc_code); 198 do_no_context(regs);
205} 199}
206 200
207static noinline void do_sigbus(struct pt_regs *regs, long int_code, 201static noinline void do_sigbus(struct pt_regs *regs)
208 unsigned long trans_exc_code)
209{ 202{
210 struct task_struct *tsk = current; 203 struct task_struct *tsk = current;
211 unsigned long address;
212 struct siginfo si; 204 struct siginfo si;
213 205
214 /* 206 /*
215 * Send a sigbus, regardless of whether we were in kernel 207 * Send a sigbus, regardless of whether we were in kernel
216 * or user mode. 208 * or user mode.
217 */ 209 */
218 address = trans_exc_code & __FAIL_ADDR_MASK;
219 tsk->thread.prot_addr = address;
220 tsk->thread.trap_no = int_code;
221 si.si_signo = SIGBUS; 210 si.si_signo = SIGBUS;
222 si.si_errno = 0; 211 si.si_errno = 0;
223 si.si_code = BUS_ADRERR; 212 si.si_code = BUS_ADRERR;
224 si.si_addr = (void __user *) address; 213 si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
225 force_sig_info(SIGBUS, &si, tsk); 214 force_sig_info(SIGBUS, &si, tsk);
226} 215}
227 216
228static noinline void do_fault_error(struct pt_regs *regs, long int_code, 217static noinline void do_fault_error(struct pt_regs *regs, int fault)
229 unsigned long trans_exc_code, int fault)
230{ 218{
231 int si_code; 219 int si_code;
232 220
@@ -238,24 +226,24 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
238 /* User mode accesses just cause a SIGSEGV */ 226 /* User mode accesses just cause a SIGSEGV */
239 si_code = (fault == VM_FAULT_BADMAP) ? 227 si_code = (fault == VM_FAULT_BADMAP) ?
240 SEGV_MAPERR : SEGV_ACCERR; 228 SEGV_MAPERR : SEGV_ACCERR;
241 do_sigsegv(regs, int_code, si_code, trans_exc_code); 229 do_sigsegv(regs, si_code);
242 return; 230 return;
243 } 231 }
244 case VM_FAULT_BADCONTEXT: 232 case VM_FAULT_BADCONTEXT:
245 do_no_context(regs, int_code, trans_exc_code); 233 do_no_context(regs);
246 break; 234 break;
247 default: /* fault & VM_FAULT_ERROR */ 235 default: /* fault & VM_FAULT_ERROR */
248 if (fault & VM_FAULT_OOM) { 236 if (fault & VM_FAULT_OOM) {
249 if (!(regs->psw.mask & PSW_MASK_PSTATE)) 237 if (!(regs->psw.mask & PSW_MASK_PSTATE))
250 do_no_context(regs, int_code, trans_exc_code); 238 do_no_context(regs);
251 else 239 else
252 pagefault_out_of_memory(); 240 pagefault_out_of_memory();
253 } else if (fault & VM_FAULT_SIGBUS) { 241 } else if (fault & VM_FAULT_SIGBUS) {
254 /* Kernel mode? Handle exceptions or die */ 242 /* Kernel mode? Handle exceptions or die */
255 if (!(regs->psw.mask & PSW_MASK_PSTATE)) 243 if (!(regs->psw.mask & PSW_MASK_PSTATE))
256 do_no_context(regs, int_code, trans_exc_code); 244 do_no_context(regs);
257 else 245 else
258 do_sigbus(regs, int_code, trans_exc_code); 246 do_sigbus(regs);
259 } else 247 } else
260 BUG(); 248 BUG();
261 break; 249 break;
@@ -273,12 +261,12 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
273 * 11 Page translation -> Not present (nullification) 261 * 11 Page translation -> Not present (nullification)
274 * 3b Region third trans. -> Not present (nullification) 262 * 3b Region third trans. -> Not present (nullification)
275 */ 263 */
276static inline int do_exception(struct pt_regs *regs, int access, 264static inline int do_exception(struct pt_regs *regs, int access)
277 unsigned long trans_exc_code)
278{ 265{
279 struct task_struct *tsk; 266 struct task_struct *tsk;
280 struct mm_struct *mm; 267 struct mm_struct *mm;
281 struct vm_area_struct *vma; 268 struct vm_area_struct *vma;
269 unsigned long trans_exc_code;
282 unsigned long address; 270 unsigned long address;
283 unsigned int flags; 271 unsigned int flags;
284 int fault; 272 int fault;
@@ -288,6 +276,7 @@ static inline int do_exception(struct pt_regs *regs, int access,
288 276
289 tsk = current; 277 tsk = current;
290 mm = tsk->mm; 278 mm = tsk->mm;
279 trans_exc_code = regs->int_parm_long;
291 280
292 /* 281 /*
293 * Verify that the fault happened in user space, that 282 * Verify that the fault happened in user space, that
@@ -387,45 +376,46 @@ out:
387 return fault; 376 return fault;
388} 377}
389 378
390void __kprobes do_protection_exception(struct pt_regs *regs, long pgm_int_code, 379void __kprobes do_protection_exception(struct pt_regs *regs)
391 unsigned long trans_exc_code)
392{ 380{
381 unsigned long trans_exc_code;
393 int fault; 382 int fault;
394 383
384 trans_exc_code = regs->int_parm_long;
395 /* Protection exception is suppressing, decrement psw address. */ 385 /* Protection exception is suppressing, decrement psw address. */
396 regs->psw.addr = __rewind_psw(regs->psw, pgm_int_code >> 16); 386 regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
397 /* 387 /*
398 * Check for low-address protection. This needs to be treated 388 * Check for low-address protection. This needs to be treated
399 * as a special case because the translation exception code 389 * as a special case because the translation exception code
400 * field is not guaranteed to contain valid data in this case. 390 * field is not guaranteed to contain valid data in this case.
401 */ 391 */
402 if (unlikely(!(trans_exc_code & 4))) { 392 if (unlikely(!(trans_exc_code & 4))) {
403 do_low_address(regs, pgm_int_code, trans_exc_code); 393 do_low_address(regs);
404 return; 394 return;
405 } 395 }
406 fault = do_exception(regs, VM_WRITE, trans_exc_code); 396 fault = do_exception(regs, VM_WRITE);
407 if (unlikely(fault)) 397 if (unlikely(fault))
408 do_fault_error(regs, 4, trans_exc_code, fault); 398 do_fault_error(regs, fault);
409} 399}
410 400
411void __kprobes do_dat_exception(struct pt_regs *regs, long pgm_int_code, 401void __kprobes do_dat_exception(struct pt_regs *regs)
412 unsigned long trans_exc_code)
413{ 402{
414 int access, fault; 403 int access, fault;
415 404
416 access = VM_READ | VM_EXEC | VM_WRITE; 405 access = VM_READ | VM_EXEC | VM_WRITE;
417 fault = do_exception(regs, access, trans_exc_code); 406 fault = do_exception(regs, access);
418 if (unlikely(fault)) 407 if (unlikely(fault))
419 do_fault_error(regs, pgm_int_code & 255, trans_exc_code, fault); 408 do_fault_error(regs, fault);
420} 409}
421 410
422#ifdef CONFIG_64BIT 411#ifdef CONFIG_64BIT
423void __kprobes do_asce_exception(struct pt_regs *regs, long pgm_int_code, 412void __kprobes do_asce_exception(struct pt_regs *regs)
424 unsigned long trans_exc_code)
425{ 413{
426 struct mm_struct *mm = current->mm; 414 struct mm_struct *mm = current->mm;
427 struct vm_area_struct *vma; 415 struct vm_area_struct *vma;
416 unsigned long trans_exc_code;
428 417
418 trans_exc_code = regs->int_parm_long;
429 if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) 419 if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm))
430 goto no_context; 420 goto no_context;
431 421
@@ -440,12 +430,12 @@ void __kprobes do_asce_exception(struct pt_regs *regs, long pgm_int_code,
440 430
441 /* User mode accesses just cause a SIGSEGV */ 431 /* User mode accesses just cause a SIGSEGV */
442 if (regs->psw.mask & PSW_MASK_PSTATE) { 432 if (regs->psw.mask & PSW_MASK_PSTATE) {
443 do_sigsegv(regs, pgm_int_code, SEGV_MAPERR, trans_exc_code); 433 do_sigsegv(regs, SEGV_MAPERR);
444 return; 434 return;
445 } 435 }
446 436
447no_context: 437no_context:
448 do_no_context(regs, pgm_int_code, trans_exc_code); 438 do_no_context(regs);
449} 439}
450#endif 440#endif
451 441
@@ -459,14 +449,15 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
459 regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; 449 regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
460 regs.psw.addr = (unsigned long) __builtin_return_address(0); 450 regs.psw.addr = (unsigned long) __builtin_return_address(0);
461 regs.psw.addr |= PSW_ADDR_AMODE; 451 regs.psw.addr |= PSW_ADDR_AMODE;
462 uaddr &= PAGE_MASK; 452 regs.int_code = pgm_int_code;
453 regs.int_parm_long = (uaddr & PAGE_MASK) | 2;
463 access = write ? VM_WRITE : VM_READ; 454 access = write ? VM_WRITE : VM_READ;
464 fault = do_exception(&regs, access, uaddr | 2); 455 fault = do_exception(&regs, access);
465 if (unlikely(fault)) { 456 if (unlikely(fault)) {
466 if (fault & VM_FAULT_OOM) 457 if (fault & VM_FAULT_OOM)
467 return -EFAULT; 458 return -EFAULT;
468 else if (fault & VM_FAULT_SIGBUS) 459 else if (fault & VM_FAULT_SIGBUS)
469 do_sigbus(&regs, pgm_int_code, uaddr); 460 do_sigbus(&regs);
470 } 461 }
471 return fault ? -EFAULT : 0; 462 return fault ? -EFAULT : 0;
472} 463}