Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Martin Schwidefsky and committed by
Martin Schwidefsky
86f2552b cd3b70f5

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