aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2010-05-17 04:00:05 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-05-17 04:00:15 -0400
commit86f2552bbd0e17b19bb5e9881042533eaea553c7 (patch)
treef520909d953f5d8c7db3dd4c4f2582bd7f7473aa /arch/s390/kernel
parentcd3b70f5d4d82f85d1e1d6e822f38ae098cf7c72 (diff)
[S390] add breaking event address for user space
Copy the last breaking event address from the lowcore to a new field in the thread_struct on each system entry. Add a new ptrace request PTRACE_GET_LAST_BREAK and a new utrace regset REGSET_LAST_BREAK to query the last breaking event. This is useful for debugging wild branches in user space code. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/asm-offsets.c1
-rw-r--r--arch/s390/kernel/entry.S4
-rw-r--r--arch/s390/kernel/entry64.S270
-rw-r--r--arch/s390/kernel/ptrace.c68
-rw-r--r--arch/s390/kernel/signal.c2
5 files changed, 219 insertions, 126 deletions
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 44a4336d9a33..d9b490a2716e 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -39,6 +39,7 @@ int main(void)
39 DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count)); 39 DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));
40 DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer)); 40 DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer));
41 DEFINE(__TI_system_timer, offsetof(struct thread_info, system_timer)); 41 DEFINE(__TI_system_timer, offsetof(struct thread_info, system_timer));
42 DEFINE(__TI_last_break, offsetof(struct thread_info, last_break));
42 BLANK(); 43 BLANK();
43 DEFINE(__PT_ARGS, offsetof(struct pt_regs, args)); 44 DEFINE(__PT_ARGS, offsetof(struct pt_regs, args));
44 DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); 45 DEFINE(__PT_PSW, offsetof(struct pt_regs, psw));
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 0e2b16241dfa..d5e3e6007447 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -180,9 +180,9 @@ STACK_SIZE = 1 << STACK_SHIFT
180 s %r15,BASED(.Lc_spsize) # make room for registers & psw 180 s %r15,BASED(.Lc_spsize) # make room for registers & psw
181 mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack 181 mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack
182 st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 182 st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
183 icm %r12,3,__LC_SVC_ILC 183 icm %r12,12,__LC_SVC_ILC
184 stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack 184 stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack
185 st %r12,SP_SVCNR(%r15) 185 st %r12,SP_ILC(%r15)
186 mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack 186 mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
187 la %r12,0 187 la %r12,0
188 st %r12,__SF_BACKCHAIN(%r15) # clear back chain 188 st %r12,__SF_BACKCHAIN(%r15) # clear back chain
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 829b759ba1e1..178d92536d90 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -126,31 +126,35 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
126 * R15 - kernel stack pointer 126 * R15 - kernel stack pointer
127 */ 127 */
128 128
129 .macro SAVE_ALL_BASE savearea
130 stmg %r12,%r15,\savearea
131 larl %r13,system_call
132 .endm
133
134 .macro SAVE_ALL_SVC psworg,savearea 129 .macro SAVE_ALL_SVC psworg,savearea
135 la %r12,\psworg 130 stmg %r11,%r15,\savearea
136 lg %r15,__LC_KERNEL_STACK # problem state -> load ksp 131 lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
132 aghi %r15,-SP_SIZE # make room for registers & psw
133 lg %r11,__LC_LAST_BREAK
137 .endm 134 .endm
138 135
139 .macro SAVE_ALL_SYNC psworg,savearea 136 .macro SAVE_ALL_PGM psworg,savearea
140 la %r12,\psworg 137 stmg %r11,%r15,\savearea
141 tm \psworg+1,0x01 # test problem state bit 138 tm \psworg+1,0x01 # test problem state bit
142 jz 2f # skip stack setup save
143 lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
144#ifdef CONFIG_CHECK_STACK 139#ifdef CONFIG_CHECK_STACK
145 j 3f 140 jnz 1f
1462: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD 141 tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
147 jz stack_overflow 142 jnz 2f
1483: 143 la %r12,\psworg
144 j stack_overflow
145#else
146 jz 2f
149#endif 147#endif
1502: 1481: lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
1492: aghi %r15,-SP_SIZE # make room for registers & psw
150 larl %r13,system_call
151 lg %r11,__LC_LAST_BREAK
151 .endm 152 .endm
152 153
153 .macro SAVE_ALL_ASYNC psworg,savearea 154 .macro SAVE_ALL_ASYNC psworg,savearea
155 stmg %r11,%r15,\savearea
156 larl %r13,system_call
157 lg %r11,__LC_LAST_BREAK
154 la %r12,\psworg 158 la %r12,\psworg
155 tm \psworg+1,0x01 # test problem state bit 159 tm \psworg+1,0x01 # test problem state bit
156 jnz 1f # from user -> load kernel stack 160 jnz 1f # from user -> load kernel stack
@@ -164,27 +168,23 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
1640: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? 1680: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ?
165 slgr %r14,%r15 169 slgr %r14,%r15
166 srag %r14,%r14,STACK_SHIFT 170 srag %r14,%r14,STACK_SHIFT
167 jz 2f
1681: lg %r15,__LC_ASYNC_STACK # load async stack
169#ifdef CONFIG_CHECK_STACK 171#ifdef CONFIG_CHECK_STACK
170 j 3f 172 jnz 1f
1712: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD 173 tml %r15,STACK_SIZE - CONFIG_STACK_GUARD
172 jz stack_overflow 174 jnz 2f
1733: 175 j stack_overflow
176#else
177 jz 2f
174#endif 178#endif
1752: 1791: lg %r15,__LC_ASYNC_STACK # load async stack
1802: aghi %r15,-SP_SIZE # make room for registers & psw
176 .endm 181 .endm
177 182
178 .macro CREATE_STACK_FRAME psworg,savearea 183 .macro CREATE_STACK_FRAME savearea
179 aghi %r15,-SP_SIZE # make room for registers & psw 184 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
180 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
181 stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 185 stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
182 icm %r12,3,__LC_SVC_ILC 186 mvc SP_R11(40,%r15),\savearea # move %r11-%r15 to stack
183 stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack 187 stmg %r0,%r10,SP_R0(%r15) # store gprs %r0-%r10 to kernel stack
184 st %r12,SP_SVCNR(%r15)
185 mvc SP_R12(32,%r15),\savearea # move %r12-%r15 to stack
186 la %r12,0
187 stg %r12,__SF_BACKCHAIN(%r15)
188 .endm 188 .endm
189 189
190 .macro RESTORE_ALL psworg,sync 190 .macro RESTORE_ALL psworg,sync
@@ -200,6 +200,13 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
200 lpswe \psworg # back to caller 200 lpswe \psworg # back to caller
201 .endm 201 .endm
202 202
203 .macro LAST_BREAK
204 srag %r10,%r11,23
205 jz 0f
206 stg %r11,__TI_last_break(%r12)
2070:
208 .endm
209
203/* 210/*
204 * Scheduler resume function, called by switch_to 211 * Scheduler resume function, called by switch_to
205 * gpr2 = (task_struct *) prev 212 * gpr2 = (task_struct *) prev
@@ -245,37 +252,38 @@ __critical_start:
245system_call: 252system_call:
246 stpt __LC_SYNC_ENTER_TIMER 253 stpt __LC_SYNC_ENTER_TIMER
247sysc_saveall: 254sysc_saveall:
248 SAVE_ALL_BASE __LC_SAVE_AREA
249 SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA 255 SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
250 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 256 CREATE_STACK_FRAME __LC_SAVE_AREA
251 llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore 257 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
258 mvc SP_ILC(4,%r15),__LC_SVC_ILC
259 stg %r7,SP_ARGS(%r15)
260 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
252sysc_vtime: 261sysc_vtime:
253 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 262 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
254sysc_stime: 263sysc_stime:
255 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 264 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
256sysc_update: 265sysc_update:
257 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 266 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
267 LAST_BREAK
258sysc_do_svc: 268sysc_do_svc:
259 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct 269 llgh %r7,SP_SVCNR(%r15)
260 ltgr %r7,%r7 # test for svc 0 270 slag %r7,%r7,2 # shift and test for svc 0
261 jnz sysc_nr_ok 271 jnz sysc_nr_ok
262 # svc 0: system call number in %r1 272 # svc 0: system call number in %r1
263 cl %r1,BASED(.Lnr_syscalls) 273 llgfr %r1,%r1 # clear high word in r1
274 cghi %r1,NR_syscalls
264 jnl sysc_nr_ok 275 jnl sysc_nr_ok
265 lgfr %r7,%r1 # clear high word in r1 276 sth %r1,SP_SVCNR(%r15)
277 slag %r7,%r1,2 # shift and test for svc 0
266sysc_nr_ok: 278sysc_nr_ok:
267 mvc SP_ARGS(8,%r15),SP_R7(%r15)
268sysc_do_restart:
269 sth %r7,SP_SVCNR(%r15)
270 sllg %r7,%r7,2 # svc number * 4
271 larl %r10,sys_call_table 279 larl %r10,sys_call_table
272#ifdef CONFIG_COMPAT 280#ifdef CONFIG_COMPAT
273 tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ? 281 tm __TI_flags+5(%r12),(_TIF_31BIT>>16) # running in 31 bit mode ?
274 jno sysc_noemu 282 jno sysc_noemu
275 larl %r10,sys_call_table_emu # use 31 bit emulation system calls 283 larl %r10,sys_call_table_emu # use 31 bit emulation system calls
276sysc_noemu: 284sysc_noemu:
277#endif 285#endif
278 tm __TI_flags+6(%r9),_TIF_SYSCALL 286 tm __TI_flags+6(%r12),_TIF_SYSCALL
279 lgf %r8,0(%r7,%r10) # load address of system call routine 287 lgf %r8,0(%r7,%r10) # load address of system call routine
280 jnz sysc_tracesys 288 jnz sysc_tracesys
281 basr %r14,%r8 # call sys_xxxx 289 basr %r14,%r8 # call sys_xxxx
@@ -284,7 +292,7 @@ sysc_noemu:
284sysc_return: 292sysc_return:
285 LOCKDEP_SYS_EXIT 293 LOCKDEP_SYS_EXIT
286sysc_tif: 294sysc_tif:
287 tm __TI_flags+7(%r9),_TIF_WORK_SVC 295 tm __TI_flags+7(%r12),_TIF_WORK_SVC
288 jnz sysc_work # there is work to do (signals etc.) 296 jnz sysc_work # there is work to do (signals etc.)
289sysc_restore: 297sysc_restore:
290 RESTORE_ALL __LC_RETURN_PSW,1 298 RESTORE_ALL __LC_RETURN_PSW,1
@@ -301,17 +309,17 @@ sysc_work:
301# One of the work bits is on. Find out which one. 309# One of the work bits is on. Find out which one.
302# 310#
303sysc_work_tif: 311sysc_work_tif:
304 tm __TI_flags+7(%r9),_TIF_MCCK_PENDING 312 tm __TI_flags+7(%r12),_TIF_MCCK_PENDING
305 jo sysc_mcck_pending 313 jo sysc_mcck_pending
306 tm __TI_flags+7(%r9),_TIF_NEED_RESCHED 314 tm __TI_flags+7(%r12),_TIF_NEED_RESCHED
307 jo sysc_reschedule 315 jo sysc_reschedule
308 tm __TI_flags+7(%r9),_TIF_SIGPENDING 316 tm __TI_flags+7(%r12),_TIF_SIGPENDING
309 jo sysc_sigpending 317 jo sysc_sigpending
310 tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME 318 tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME
311 jo sysc_notify_resume 319 jo sysc_notify_resume
312 tm __TI_flags+7(%r9),_TIF_RESTART_SVC 320 tm __TI_flags+7(%r12),_TIF_RESTART_SVC
313 jo sysc_restart 321 jo sysc_restart
314 tm __TI_flags+7(%r9),_TIF_SINGLE_STEP 322 tm __TI_flags+7(%r12),_TIF_SINGLE_STEP
315 jo sysc_singlestep 323 jo sysc_singlestep
316 j sysc_return # beware of critical section cleanup 324 j sysc_return # beware of critical section cleanup
317 325
@@ -333,12 +341,12 @@ sysc_mcck_pending:
333# _TIF_SIGPENDING is set, call do_signal 341# _TIF_SIGPENDING is set, call do_signal
334# 342#
335sysc_sigpending: 343sysc_sigpending:
336 ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP 344 ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
337 la %r2,SP_PTREGS(%r15) # load pt_regs 345 la %r2,SP_PTREGS(%r15) # load pt_regs
338 brasl %r14,do_signal # call do_signal 346 brasl %r14,do_signal # call do_signal
339 tm __TI_flags+7(%r9),_TIF_RESTART_SVC 347 tm __TI_flags+7(%r12),_TIF_RESTART_SVC
340 jo sysc_restart 348 jo sysc_restart
341 tm __TI_flags+7(%r9),_TIF_SINGLE_STEP 349 tm __TI_flags+7(%r12),_TIF_SINGLE_STEP
342 jo sysc_singlestep 350 jo sysc_singlestep
343 j sysc_return 351 j sysc_return
344 352
@@ -354,17 +362,19 @@ sysc_notify_resume:
354# _TIF_RESTART_SVC is set, set up registers and restart svc 362# _TIF_RESTART_SVC is set, set up registers and restart svc
355# 363#
356sysc_restart: 364sysc_restart:
357 ni __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC 365 ni __TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
358 lg %r7,SP_R2(%r15) # load new svc number 366 lg %r7,SP_R2(%r15) # load new svc number
359 mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument 367 mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
360 lmg %r2,%r6,SP_R2(%r15) # load svc arguments 368 lmg %r2,%r6,SP_R2(%r15) # load svc arguments
361 j sysc_do_restart # restart svc 369 sth %r7,SP_SVCNR(%r15)
370 slag %r7,%r7,2
371 j sysc_nr_ok # restart svc
362 372
363# 373#
364# _TIF_SINGLE_STEP is set, call do_single_step 374# _TIF_SINGLE_STEP is set, call do_single_step
365# 375#
366sysc_singlestep: 376sysc_singlestep:
367 ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP 377 ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
368 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number 378 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
369 la %r2,SP_PTREGS(%r15) # address of register-save area 379 la %r2,SP_PTREGS(%r15) # address of register-save area
370 larl %r14,sysc_return # load adr. of system return 380 larl %r14,sysc_return # load adr. of system return
@@ -377,8 +387,8 @@ sysc_singlestep:
377sysc_tracesys: 387sysc_tracesys:
378 la %r2,SP_PTREGS(%r15) # load pt_regs 388 la %r2,SP_PTREGS(%r15) # load pt_regs
379 la %r3,0 389 la %r3,0
380 srl %r7,2 390 llgh %r0,SP_SVCNR(%r15)
381 stg %r7,SP_R2(%r15) 391 stg %r0,SP_R2(%r15)
382 brasl %r14,do_syscall_trace_enter 392 brasl %r14,do_syscall_trace_enter
383 lghi %r0,NR_syscalls 393 lghi %r0,NR_syscalls
384 clgr %r0,%r2 394 clgr %r0,%r2
@@ -391,7 +401,7 @@ sysc_tracego:
391 basr %r14,%r8 # call sys_xxx 401 basr %r14,%r8 # call sys_xxx
392 stg %r2,SP_R2(%r15) # store return value 402 stg %r2,SP_R2(%r15) # store return value
393sysc_tracenogo: 403sysc_tracenogo:
394 tm __TI_flags+6(%r9),_TIF_SYSCALL 404 tm __TI_flags+6(%r12),_TIF_SYSCALL
395 jz sysc_return 405 jz sysc_return
396 la %r2,SP_PTREGS(%r15) # load pt_regs 406 la %r2,SP_PTREGS(%r15) # load pt_regs
397 larl %r14,sysc_return # return point is sysc_return 407 larl %r14,sysc_return # return point is sysc_return
@@ -403,7 +413,7 @@ sysc_tracenogo:
403 .globl ret_from_fork 413 .globl ret_from_fork
404ret_from_fork: 414ret_from_fork:
405 lg %r13,__LC_SVC_NEW_PSW+8 415 lg %r13,__LC_SVC_NEW_PSW+8
406 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct 416 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
407 tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? 417 tm SP_PSW+1(%r15),0x01 # forking a kernel thread ?
408 jo 0f 418 jo 0f
409 stg %r15,SP_R15(%r15) # store stack pointer for new kthread 419 stg %r15,SP_R15(%r15) # store stack pointer for new kthread
@@ -437,8 +447,8 @@ kernel_execve:
437 lg %r15,__LC_KERNEL_STACK # load ksp 447 lg %r15,__LC_KERNEL_STACK # load ksp
438 aghi %r15,-SP_SIZE # make room for registers & psw 448 aghi %r15,-SP_SIZE # make room for registers & psw
439 lg %r13,__LC_SVC_NEW_PSW+8 449 lg %r13,__LC_SVC_NEW_PSW+8
440 lg %r9,__LC_THREAD_INFO
441 mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs 450 mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs
451 lg %r12,__LC_THREAD_INFO
442 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 452 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
443# TRACE_IRQS_ON 453# TRACE_IRQS_ON
444 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 454 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
@@ -465,21 +475,23 @@ pgm_check_handler:
465 * for LPSW?). 475 * for LPSW?).
466 */ 476 */
467 stpt __LC_SYNC_ENTER_TIMER 477 stpt __LC_SYNC_ENTER_TIMER
468 SAVE_ALL_BASE __LC_SAVE_AREA
469 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception 478 tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
470 jnz pgm_per # got per exception -> special case 479 jnz pgm_per # got per exception -> special case
471 SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA 480 SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
472 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA 481 CREATE_STACK_FRAME __LC_SAVE_AREA
482 xc SP_ILC(4,%r15),SP_ILC(%r15)
483 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
484 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
473 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 485 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
474 jz pgm_no_vtime 486 jz pgm_no_vtime
475 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 487 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
476 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 488 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
477 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 489 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
490 LAST_BREAK
478pgm_no_vtime: 491pgm_no_vtime:
479 HANDLE_SIE_INTERCEPT 492 HANDLE_SIE_INTERCEPT
480 TRACE_IRQS_CHECK_OFF 493 TRACE_IRQS_CHECK_OFF
481 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct 494 stg %r11,SP_ARGS(%r15)
482 mvc SP_ARGS(8,%r15),__LC_LAST_BREAK
483 lgf %r3,__LC_PGM_ILC # load program interruption code 495 lgf %r3,__LC_PGM_ILC # load program interruption code
484 lghi %r8,0x7f 496 lghi %r8,0x7f
485 ngr %r8,%r3 497 ngr %r8,%r3
@@ -503,31 +515,32 @@ pgm_per:
503 clc __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW 515 clc __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
504 je pgm_svcper 516 je pgm_svcper
505# no interesting special case, ignore PER event 517# no interesting special case, ignore PER event
506 lmg %r12,%r15,__LC_SAVE_AREA
507 lpswe __LC_PGM_OLD_PSW 518 lpswe __LC_PGM_OLD_PSW
508 519
509# 520#
510# Normal per exception 521# Normal per exception
511# 522#
512pgm_per_std: 523pgm_per_std:
513 SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA 524 SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA
514 CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA 525 CREATE_STACK_FRAME __LC_SAVE_AREA
526 mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW
527 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
515 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 528 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
516 jz pgm_no_vtime2 529 jz pgm_no_vtime2
517 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 530 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
518 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 531 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
519 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 532 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
533 LAST_BREAK
520pgm_no_vtime2: 534pgm_no_vtime2:
521 HANDLE_SIE_INTERCEPT 535 HANDLE_SIE_INTERCEPT
522 TRACE_IRQS_CHECK_OFF 536 TRACE_IRQS_CHECK_OFF
523 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct 537 lg %r1,__TI_task(%r12)
524 lg %r1,__TI_task(%r9)
525 tm SP_PSW+1(%r15),0x01 # kernel per event ? 538 tm SP_PSW+1(%r15),0x01 # kernel per event ?
526 jz kernel_per 539 jz kernel_per
527 mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID 540 mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID
528 mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS 541 mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
529 mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID 542 mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
530 oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP 543 oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
531 lgf %r3,__LC_PGM_ILC # load program interruption code 544 lgf %r3,__LC_PGM_ILC # load program interruption code
532 lghi %r8,0x7f 545 lghi %r8,0x7f
533 ngr %r8,%r3 # clear per-event-bit and ilc 546 ngr %r8,%r3 # clear per-event-bit and ilc
@@ -538,19 +551,21 @@ pgm_no_vtime2:
538# it was a single stepped SVC that is causing all the trouble 551# it was a single stepped SVC that is causing all the trouble
539# 552#
540pgm_svcper: 553pgm_svcper:
541 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA 554 SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA
542 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 555 CREATE_STACK_FRAME __LC_SAVE_AREA
556 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
557 mvc SP_ILC(4,%r15),__LC_SVC_ILC
558 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
543 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER 559 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
544 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 560 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
545 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 561 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
546 llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore 562 LAST_BREAK
547 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
548 TRACE_IRQS_OFF 563 TRACE_IRQS_OFF
549 lg %r8,__TI_task(%r9) 564 lg %r8,__TI_task(%r12)
550 mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID 565 mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID
551 mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS 566 mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS
552 mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID 567 mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID
553 oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP 568 oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
554 TRACE_IRQS_ON 569 TRACE_IRQS_ON
555 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts 570 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
556 lmg %r2,%r6,SP_R2(%r15) # load svc arguments 571 lmg %r2,%r6,SP_R2(%r15) # load svc arguments
@@ -572,16 +587,17 @@ kernel_per:
572io_int_handler: 587io_int_handler:
573 stck __LC_INT_CLOCK 588 stck __LC_INT_CLOCK
574 stpt __LC_ASYNC_ENTER_TIMER 589 stpt __LC_ASYNC_ENTER_TIMER
575 SAVE_ALL_BASE __LC_SAVE_AREA+32 590 SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+40
576 SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 591 CREATE_STACK_FRAME __LC_SAVE_AREA+40
577 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 592 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
593 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
578 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 594 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
579 jz io_no_vtime 595 jz io_no_vtime
580 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 596 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
581 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 597 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
582 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 598 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
599 LAST_BREAK
583io_no_vtime: 600io_no_vtime:
584 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
585 HANDLE_SIE_INTERCEPT 601 HANDLE_SIE_INTERCEPT
586 TRACE_IRQS_OFF 602 TRACE_IRQS_OFF
587 la %r2,SP_PTREGS(%r15) # address of register-save area 603 la %r2,SP_PTREGS(%r15) # address of register-save area
@@ -590,7 +606,7 @@ io_return:
590 LOCKDEP_SYS_EXIT 606 LOCKDEP_SYS_EXIT
591 TRACE_IRQS_ON 607 TRACE_IRQS_ON
592io_tif: 608io_tif:
593 tm __TI_flags+7(%r9),_TIF_WORK_INT 609 tm __TI_flags+7(%r12),_TIF_WORK_INT
594 jnz io_work # there is work to do (signals etc.) 610 jnz io_work # there is work to do (signals etc.)
595io_restore: 611io_restore:
596 RESTORE_ALL __LC_RETURN_PSW,0 612 RESTORE_ALL __LC_RETURN_PSW,0
@@ -610,7 +626,7 @@ io_work:
610 jo io_work_user # yes -> do resched & signal 626 jo io_work_user # yes -> do resched & signal
611#ifdef CONFIG_PREEMPT 627#ifdef CONFIG_PREEMPT
612 # check for preemptive scheduling 628 # check for preemptive scheduling
613 icm %r0,15,__TI_precount(%r9) 629 icm %r0,15,__TI_precount(%r12)
614 jnz io_restore # preemption is disabled 630 jnz io_restore # preemption is disabled
615 tm __TI_flags+7(%r12),_TIF_NEED_RESCHED 631 tm __TI_flags+7(%r12),_TIF_NEED_RESCHED
616 jno io_restore 632 jno io_restore
@@ -645,13 +661,13 @@ io_work_user:
645# and _TIF_MCCK_PENDING 661# and _TIF_MCCK_PENDING
646# 662#
647io_work_tif: 663io_work_tif:
648 tm __TI_flags+7(%r9),_TIF_MCCK_PENDING 664 tm __TI_flags+7(%r12),_TIF_MCCK_PENDING
649 jo io_mcck_pending 665 jo io_mcck_pending
650 tm __TI_flags+7(%r9),_TIF_NEED_RESCHED 666 tm __TI_flags+7(%r12),_TIF_NEED_RESCHED
651 jo io_reschedule 667 jo io_reschedule
652 tm __TI_flags+7(%r9),_TIF_SIGPENDING 668 tm __TI_flags+7(%r12),_TIF_SIGPENDING
653 jo io_sigpending 669 jo io_sigpending
654 tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME 670 tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME
655 jo io_notify_resume 671 jo io_notify_resume
656 j io_return # beware of critical section cleanup 672 j io_return # beware of critical section cleanup
657 673
@@ -706,16 +722,17 @@ io_notify_resume:
706ext_int_handler: 722ext_int_handler:
707 stck __LC_INT_CLOCK 723 stck __LC_INT_CLOCK
708 stpt __LC_ASYNC_ENTER_TIMER 724 stpt __LC_ASYNC_ENTER_TIMER
709 SAVE_ALL_BASE __LC_SAVE_AREA+32 725 SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+40
710 SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 726 CREATE_STACK_FRAME __LC_SAVE_AREA+40
711 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 727 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
728 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
712 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 729 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
713 jz ext_no_vtime 730 jz ext_no_vtime
714 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER 731 UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
715 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 732 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
716 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER 733 mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
734 LAST_BREAK
717ext_no_vtime: 735ext_no_vtime:
718 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
719 HANDLE_SIE_INTERCEPT 736 HANDLE_SIE_INTERCEPT
720 TRACE_IRQS_OFF 737 TRACE_IRQS_OFF
721 la %r2,SP_PTREGS(%r15) # address of register-save area 738 la %r2,SP_PTREGS(%r15) # address of register-save area
@@ -734,7 +751,9 @@ mcck_int_handler:
734 la %r1,4095 # revalidate r1 751 la %r1,4095 # revalidate r1
735 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer 752 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
736 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs 753 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
737 SAVE_ALL_BASE __LC_SAVE_AREA+64 754 stmg %r11,%r15,__LC_SAVE_AREA+80
755 larl %r13,system_call
756 lg %r11,__LC_LAST_BREAK
738 la %r12,__LC_MCK_OLD_PSW 757 la %r12,__LC_MCK_OLD_PSW
739 tm __LC_MCCK_CODE,0x80 # system damage? 758 tm __LC_MCCK_CODE,0x80 # system damage?
740 jo mcck_int_main # yes -> rest of mcck code invalid 759 jo mcck_int_main # yes -> rest of mcck code invalid
@@ -769,7 +788,10 @@ mcck_int_main:
769 srag %r14,%r14,PAGE_SHIFT 788 srag %r14,%r14,PAGE_SHIFT
770 jz 0f 789 jz 0f
771 lg %r15,__LC_PANIC_STACK # load panic stack 790 lg %r15,__LC_PANIC_STACK # load panic stack
7720: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 7910: aghi %r15,-SP_SIZE # make room for registers & psw
792 CREATE_STACK_FRAME __LC_SAVE_AREA+80
793 mvc SP_PSW(16,%r15),0(%r12)
794 lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct
773 tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? 795 tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
774 jno mcck_no_vtime # no -> no timer update 796 jno mcck_no_vtime # no -> no timer update
775 tm SP_PSW+1(%r15),0x01 # interrupting from user ? 797 tm SP_PSW+1(%r15),0x01 # interrupting from user ?
@@ -777,8 +799,8 @@ mcck_int_main:
777 UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER 799 UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
778 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 800 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
779 mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER 801 mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER
802 LAST_BREAK
780mcck_no_vtime: 803mcck_no_vtime:
781 lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
782 la %r2,SP_PTREGS(%r15) # load pt_regs 804 la %r2,SP_PTREGS(%r15) # load pt_regs
783 brasl %r14,s390_do_machine_check 805 brasl %r14,s390_do_machine_check
784 tm SP_PSW+1(%r15),0x01 # returning to user ? 806 tm SP_PSW+1(%r15),0x01 # returning to user ?
@@ -789,7 +811,7 @@ mcck_no_vtime:
789 xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain 811 xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
790 lgr %r15,%r1 812 lgr %r15,%r1
791 stosm __SF_EMPTY(%r15),0x04 # turn dat on 813 stosm __SF_EMPTY(%r15),0x04 # turn dat on
792 tm __TI_flags+7(%r9),_TIF_MCCK_PENDING 814 tm __TI_flags+7(%r12),_TIF_MCCK_PENDING
793 jno mcck_return 815 jno mcck_return
794 HANDLE_SIE_INTERCEPT 816 HANDLE_SIE_INTERCEPT
795 TRACE_IRQS_OFF 817 TRACE_IRQS_OFF
@@ -803,6 +825,7 @@ mcck_return:
803 jno 0f 825 jno 0f
804 stpt __LC_EXIT_TIMER 826 stpt __LC_EXIT_TIMER
8050: lpswe __LC_RETURN_MCCK_PSW # back to caller 8270: lpswe __LC_RETURN_MCCK_PSW # back to caller
828mcck_done:
806 829
807/* 830/*
808 * Restart interruption handler, kick starter for additional CPUs 831 * Restart interruption handler, kick starter for additional CPUs
@@ -858,14 +881,14 @@ stack_overflow:
858 lg %r15,__LC_PANIC_STACK # change to panic stack 881 lg %r15,__LC_PANIC_STACK # change to panic stack
859 aghi %r15,-SP_SIZE 882 aghi %r15,-SP_SIZE
860 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack 883 mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
861 stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack 884 stmg %r0,%r10,SP_R0(%r15) # store gprs %r0-%r10 to kernel stack
862 la %r1,__LC_SAVE_AREA 885 la %r1,__LC_SAVE_AREA
863 chi %r12,__LC_SVC_OLD_PSW 886 chi %r12,__LC_SVC_OLD_PSW
864 je 0f 887 je 0f
865 chi %r12,__LC_PGM_OLD_PSW 888 chi %r12,__LC_PGM_OLD_PSW
866 je 0f 889 je 0f
867 la %r1,__LC_SAVE_AREA+32 890 la %r1,__LC_SAVE_AREA+40
8680: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack 8910: mvc SP_R11(40,%r15),0(%r1) # move %r11-%r15 to stack
869 mvc SP_ARGS(8,%r15),__LC_LAST_BREAK 892 mvc SP_ARGS(8,%r15),__LC_LAST_BREAK
870 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain 893 xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
871 la %r2,SP_PTREGS(%r15) # load pt_regs 894 la %r2,SP_PTREGS(%r15) # load pt_regs
@@ -920,21 +943,23 @@ cleanup_system_call:
920 je 0f 943 je 0f
921 mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER 944 mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER
9220: cghi %r12,__LC_MCK_OLD_PSW 9450: cghi %r12,__LC_MCK_OLD_PSW
923 la %r12,__LC_SAVE_AREA+64 946 la %r12,__LC_SAVE_AREA+80
924 je 0f 947 je 0f
925 la %r12,__LC_SAVE_AREA+32 948 la %r12,__LC_SAVE_AREA+40
9260: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) 9490: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16)
927 jhe cleanup_vtime 950 jhe cleanup_vtime
928 clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) 951 clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn)
929 jh 0f 952 jh 0f
930 mvc __LC_SAVE_AREA(32),0(%r12) 953 mvc __LC_SAVE_AREA(40),0(%r12)
9310: stg %r13,8(%r12) 9540: lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
932 stg %r12,__LC_SAVE_AREA+96 # argh 955 aghi %r15,-SP_SIZE # make room for registers & psw
933 SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA 956 stg %r15,32(%r12)
934 CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA 957 stg %r11,0(%r12)
935 lg %r12,__LC_SAVE_AREA+96 # argh 958 CREATE_STACK_FRAME __LC_SAVE_AREA
936 stg %r15,24(%r12) 959 mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW
937 llgh %r7,__LC_SVC_INT_CODE 960 mvc SP_ILC(4,%r15),__LC_SVC_ILC
961 stg %r7,SP_ARGS(%r15)
962 mvc 8(8,%r12),__LC_THREAD_INFO
938cleanup_vtime: 963cleanup_vtime:
939 clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) 964 clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24)
940 jhe cleanup_stime 965 jhe cleanup_stime
@@ -945,7 +970,11 @@ cleanup_stime:
945 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER 970 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
946cleanup_update: 971cleanup_update:
947 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER 972 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
948 mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) 973 srag %r12,%r11,23
974 lg %r12,__LC_THREAD_INFO
975 jz 0f
976 stg %r11,__TI_last_break(%r12)
9770: mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8)
949 la %r12,__LC_RETURN_PSW 978 la %r12,__LC_RETURN_PSW
950 br %r14 979 br %r14
951cleanup_system_call_insn: 980cleanup_system_call_insn:
@@ -972,11 +1001,11 @@ cleanup_sysc_restore:
972 mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 1001 mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
9730: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) 10020: mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
974 cghi %r12,__LC_MCK_OLD_PSW 1003 cghi %r12,__LC_MCK_OLD_PSW
975 la %r12,__LC_SAVE_AREA+64 1004 la %r12,__LC_SAVE_AREA+80
976 je 1f 1005 je 1f
977 la %r12,__LC_SAVE_AREA+32 1006 la %r12,__LC_SAVE_AREA+40
9781: mvc 0(32,%r12),SP_R12(%r15) 10071: mvc 0(40,%r12),SP_R11(%r15)
979 lmg %r0,%r11,SP_R0(%r15) 1008 lmg %r0,%r10,SP_R0(%r15)
980 lg %r15,SP_R15(%r15) 1009 lg %r15,SP_R15(%r15)
9812: la %r12,__LC_RETURN_PSW 10102: la %r12,__LC_RETURN_PSW
982 br %r14 1011 br %r14
@@ -997,8 +1026,8 @@ cleanup_io_restore:
997 jhe 0f 1026 jhe 0f
998 mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER 1027 mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
9990: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) 10280: mvc __LC_RETURN_PSW(16),SP_PSW(%r15)
1000 mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) 1029 mvc __LC_SAVE_AREA+80(40),SP_R11(%r15)
1001 lmg %r0,%r11,SP_R0(%r15) 1030 lmg %r0,%r10,SP_R0(%r15)
1002 lg %r15,SP_R15(%r15) 1031 lg %r15,SP_R15(%r15)
10031: la %r12,__LC_RETURN_PSW 10321: la %r12,__LC_RETURN_PSW
1004 br %r14 1033 br %r14
@@ -1010,13 +1039,6 @@ cleanup_io_restore_insn:
1010 * Integer constants 1039 * Integer constants
1011 */ 1040 */
1012 .align 4 1041 .align 4
1013.Lconst:
1014.Lnr_syscalls: .long NR_syscalls
1015.L0x0130: .short 0x130
1016.L0x0140: .short 0x140
1017.L0x0150: .short 0x150
1018.L0x0160: .short 0x160
1019.L0x0170: .short 0x170
1020.Lcritical_start: 1042.Lcritical_start:
1021 .quad __critical_start 1043 .quad __critical_start
1022.Lcritical_end: 1044.Lcritical_end:
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 9f654da4cecc..83339d33c4b1 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -57,6 +57,7 @@
57enum s390_regset { 57enum s390_regset {
58 REGSET_GENERAL, 58 REGSET_GENERAL,
59 REGSET_FP, 59 REGSET_FP,
60 REGSET_LAST_BREAK,
60 REGSET_GENERAL_EXTENDED, 61 REGSET_GENERAL_EXTENDED,
61}; 62};
62 63
@@ -381,6 +382,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
381 copied += sizeof(unsigned long); 382 copied += sizeof(unsigned long);
382 } 383 }
383 return 0; 384 return 0;
385 case PTRACE_GET_LAST_BREAK:
386 put_user(task_thread_info(child)->last_break,
387 (unsigned long __user *) data);
388 return 0;
384 default: 389 default:
385 /* Removing high order bit from addr (only for 31 bit). */ 390 /* Removing high order bit from addr (only for 31 bit). */
386 addr &= PSW_ADDR_INSN; 391 addr &= PSW_ADDR_INSN;
@@ -633,6 +638,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
633 copied += sizeof(unsigned int); 638 copied += sizeof(unsigned int);
634 } 639 }
635 return 0; 640 return 0;
641 case PTRACE_GET_LAST_BREAK:
642 put_user(task_thread_info(child)->last_break,
643 (unsigned int __user *) data);
644 return 0;
636 } 645 }
637 return compat_ptrace_request(child, request, addr, data); 646 return compat_ptrace_request(child, request, addr, data);
638} 647}
@@ -797,6 +806,28 @@ static int s390_fpregs_set(struct task_struct *target,
797 return rc; 806 return rc;
798} 807}
799 808
809#ifdef CONFIG_64BIT
810
811static int s390_last_break_get(struct task_struct *target,
812 const struct user_regset *regset,
813 unsigned int pos, unsigned int count,
814 void *kbuf, void __user *ubuf)
815{
816 if (count > 0) {
817 if (kbuf) {
818 unsigned long *k = kbuf;
819 *k = task_thread_info(target)->last_break;
820 } else {
821 unsigned long __user *u = ubuf;
822 if (__put_user(task_thread_info(target)->last_break, u))
823 return -EFAULT;
824 }
825 }
826 return 0;
827}
828
829#endif
830
800static const struct user_regset s390_regsets[] = { 831static const struct user_regset s390_regsets[] = {
801 [REGSET_GENERAL] = { 832 [REGSET_GENERAL] = {
802 .core_note_type = NT_PRSTATUS, 833 .core_note_type = NT_PRSTATUS,
@@ -814,6 +845,15 @@ static const struct user_regset s390_regsets[] = {
814 .get = s390_fpregs_get, 845 .get = s390_fpregs_get,
815 .set = s390_fpregs_set, 846 .set = s390_fpregs_set,
816 }, 847 },
848#ifdef CONFIG_64BIT
849 [REGSET_LAST_BREAK] = {
850 .core_note_type = NT_S390_LAST_BREAK,
851 .n = 1,
852 .size = sizeof(long),
853 .align = sizeof(long),
854 .get = s390_last_break_get,
855 },
856#endif
817}; 857};
818 858
819static const struct user_regset_view user_s390_view = { 859static const struct user_regset_view user_s390_view = {
@@ -948,6 +988,27 @@ static int s390_compat_regs_high_set(struct task_struct *target,
948 return rc; 988 return rc;
949} 989}
950 990
991static int s390_compat_last_break_get(struct task_struct *target,
992 const struct user_regset *regset,
993 unsigned int pos, unsigned int count,
994 void *kbuf, void __user *ubuf)
995{
996 compat_ulong_t last_break;
997
998 if (count > 0) {
999 last_break = task_thread_info(target)->last_break;
1000 if (kbuf) {
1001 unsigned long *k = kbuf;
1002 *k = last_break;
1003 } else {
1004 unsigned long __user *u = ubuf;
1005 if (__put_user(last_break, u))
1006 return -EFAULT;
1007 }
1008 }
1009 return 0;
1010}
1011
951static const struct user_regset s390_compat_regsets[] = { 1012static const struct user_regset s390_compat_regsets[] = {
952 [REGSET_GENERAL] = { 1013 [REGSET_GENERAL] = {
953 .core_note_type = NT_PRSTATUS, 1014 .core_note_type = NT_PRSTATUS,
@@ -965,6 +1026,13 @@ static const struct user_regset s390_compat_regsets[] = {
965 .get = s390_fpregs_get, 1026 .get = s390_fpregs_get,
966 .set = s390_fpregs_set, 1027 .set = s390_fpregs_set,
967 }, 1028 },
1029 [REGSET_LAST_BREAK] = {
1030 .core_note_type = NT_S390_LAST_BREAK,
1031 .n = 1,
1032 .size = sizeof(long),
1033 .align = sizeof(long),
1034 .get = s390_compat_last_break_get,
1035 },
968 [REGSET_GENERAL_EXTENDED] = { 1036 [REGSET_GENERAL_EXTENDED] = {
969 .core_note_type = NT_S390_HIGH_GPRS, 1037 .core_note_type = NT_S390_HIGH_GPRS,
970 .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t), 1038 .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t),
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 6289945562b0..ee7ac8b11782 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -313,6 +313,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
313 To avoid breaking binary compatibility, they are passed as args. */ 313 To avoid breaking binary compatibility, they are passed as args. */
314 regs->gprs[4] = current->thread.trap_no; 314 regs->gprs[4] = current->thread.trap_no;
315 regs->gprs[5] = current->thread.prot_addr; 315 regs->gprs[5] = current->thread.prot_addr;
316 regs->gprs[6] = task_thread_info(current)->last_break;
316 317
317 /* Place signal number on stack to allow backtrace from handler. */ 318 /* Place signal number on stack to allow backtrace from handler. */
318 if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) 319 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
@@ -376,6 +377,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
376 regs->gprs[2] = map_signal(sig); 377 regs->gprs[2] = map_signal(sig);
377 regs->gprs[3] = (unsigned long) &frame->info; 378 regs->gprs[3] = (unsigned long) &frame->info;
378 regs->gprs[4] = (unsigned long) &frame->uc; 379 regs->gprs[4] = (unsigned long) &frame->uc;
380 regs->gprs[5] = task_thread_info(current)->last_break;
379 return 0; 381 return 0;
380 382
381give_sigsegv: 383give_sigsegv: