diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2010-05-17 04:00:05 -0400 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-05-17 04:00:15 -0400 |
commit | 86f2552bbd0e17b19bb5e9881042533eaea553c7 (patch) | |
tree | f520909d953f5d8c7db3dd4c4f2582bd7f7473aa | |
parent | cd3b70f5d4d82f85d1e1d6e822f38ae098cf7c72 (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>
-rw-r--r-- | arch/s390/include/asm/ptrace.h | 3 | ||||
-rw-r--r-- | arch/s390/include/asm/thread_info.h | 1 | ||||
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 4 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 270 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 68 | ||||
-rw-r--r-- | arch/s390/kernel/signal.c | 2 | ||||
-rw-r--r-- | include/linux/elf.h | 1 |
8 files changed, 223 insertions, 127 deletions
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index fef9b33cdd59..e2c218dc68a6 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h | |||
@@ -328,8 +328,8 @@ struct pt_regs | |||
328 | psw_t psw; | 328 | psw_t psw; |
329 | unsigned long gprs[NUM_GPRS]; | 329 | unsigned long gprs[NUM_GPRS]; |
330 | unsigned long orig_gpr2; | 330 | unsigned long orig_gpr2; |
331 | unsigned short svcnr; | ||
332 | unsigned short ilc; | 331 | unsigned short ilc; |
332 | unsigned short svcnr; | ||
333 | }; | 333 | }; |
334 | #endif | 334 | #endif |
335 | 335 | ||
@@ -436,6 +436,7 @@ typedef struct | |||
436 | #define PTRACE_PEEKDATA_AREA 0x5003 | 436 | #define PTRACE_PEEKDATA_AREA 0x5003 |
437 | #define PTRACE_POKETEXT_AREA 0x5004 | 437 | #define PTRACE_POKETEXT_AREA 0x5004 |
438 | #define PTRACE_POKEDATA_AREA 0x5005 | 438 | #define PTRACE_POKEDATA_AREA 0x5005 |
439 | #define PTRACE_GET_LAST_BREAK 0x5006 | ||
439 | 440 | ||
440 | /* | 441 | /* |
441 | * PT_PROT definition is loosely based on hppa bsd definition in | 442 | * PT_PROT definition is loosely based on hppa bsd definition in |
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 34f0873d6525..be3d3f91d86c 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h | |||
@@ -50,6 +50,7 @@ struct thread_info { | |||
50 | struct restart_block restart_block; | 50 | struct restart_block restart_block; |
51 | __u64 user_timer; | 51 | __u64 user_timer; |
52 | __u64 system_timer; | 52 | __u64 system_timer; |
53 | unsigned long last_break; /* last breaking-event-address. */ | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | /* | 56 | /* |
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 |
146 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | 141 | tml %r15,STACK_SIZE - CONFIG_STACK_GUARD |
147 | jz stack_overflow | 142 | jnz 2f |
148 | 3: | 143 | la %r12,\psworg |
144 | j stack_overflow | ||
145 | #else | ||
146 | jz 2f | ||
149 | #endif | 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 | .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 | \ | |||
164 | 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? | 168 | 0: 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 | ||
168 | 1: lg %r15,__LC_ASYNC_STACK # load async stack | ||
169 | #ifdef CONFIG_CHECK_STACK | 171 | #ifdef CONFIG_CHECK_STACK |
170 | j 3f | 172 | jnz 1f |
171 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | 173 | tml %r15,STACK_SIZE - CONFIG_STACK_GUARD |
172 | jz stack_overflow | 174 | jnz 2f |
173 | 3: | 175 | j stack_overflow |
176 | #else | ||
177 | jz 2f | ||
174 | #endif | 178 | #endif |
175 | 2: | 179 | 1: lg %r15,__LC_ASYNC_STACK # load async stack |
180 | 2: 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) | ||
207 | 0: | ||
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: | |||
245 | system_call: | 252 | system_call: |
246 | stpt __LC_SYNC_ENTER_TIMER | 253 | stpt __LC_SYNC_ENTER_TIMER |
247 | sysc_saveall: | 254 | sysc_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 | ||
252 | sysc_vtime: | 261 | sysc_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 |
254 | sysc_stime: | 263 | sysc_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 |
256 | sysc_update: | 265 | sysc_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 | ||
258 | sysc_do_svc: | 268 | sysc_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 | ||
266 | sysc_nr_ok: | 278 | sysc_nr_ok: |
267 | mvc SP_ARGS(8,%r15),SP_R7(%r15) | ||
268 | sysc_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 |
276 | sysc_noemu: | 284 | sysc_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: | |||
284 | sysc_return: | 292 | sysc_return: |
285 | LOCKDEP_SYS_EXIT | 293 | LOCKDEP_SYS_EXIT |
286 | sysc_tif: | 294 | sysc_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.) |
289 | sysc_restore: | 297 | sysc_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 | # |
303 | sysc_work_tif: | 311 | sysc_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 | # |
335 | sysc_sigpending: | 343 | sysc_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 | # |
356 | sysc_restart: | 364 | sysc_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 | # |
366 | sysc_singlestep: | 376 | sysc_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: | |||
377 | sysc_tracesys: | 387 | sysc_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 |
393 | sysc_tracenogo: | 403 | sysc_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 |
404 | ret_from_fork: | 414 | ret_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 | ||
478 | pgm_no_vtime: | 491 | pgm_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 | # |
512 | pgm_per_std: | 523 | pgm_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 | ||
520 | pgm_no_vtime2: | 534 | pgm_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 | # |
540 | pgm_svcper: | 553 | pgm_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: | |||
572 | io_int_handler: | 587 | io_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 | ||
583 | io_no_vtime: | 600 | io_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 |
592 | io_tif: | 608 | io_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.) |
595 | io_restore: | 611 | io_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 | # |
647 | io_work_tif: | 663 | io_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: | |||
706 | ext_int_handler: | 722 | ext_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 | ||
717 | ext_no_vtime: | 735 | ext_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 |
772 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 | 791 | 0: 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 | ||
780 | mcck_no_vtime: | 803 | mcck_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 |
805 | 0: lpswe __LC_RETURN_MCCK_PSW # back to caller | 827 | 0: lpswe __LC_RETURN_MCCK_PSW # back to caller |
828 | mcck_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 |
868 | 0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack | 891 | 0: 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 |
922 | 0: cghi %r12,__LC_MCK_OLD_PSW | 945 | 0: 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 |
926 | 0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) | 949 | 0: 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) |
931 | 0: stg %r13,8(%r12) | 954 | 0: 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 | ||
938 | cleanup_vtime: | 963 | cleanup_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 |
946 | cleanup_update: | 971 | cleanup_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) | ||
977 | 0: 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 |
951 | cleanup_system_call_insn: | 980 | cleanup_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 |
973 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | 1002 | 0: 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 |
978 | 1: mvc 0(32,%r12),SP_R12(%r15) | 1007 | 1: 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) |
981 | 2: la %r12,__LC_RETURN_PSW | 1010 | 2: 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 |
999 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | 1028 | 0: 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) |
1003 | 1: la %r12,__LC_RETURN_PSW | 1032 | 1: 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 @@ | |||
57 | enum s390_regset { | 57 | enum 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 | |||
811 | static 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 | |||
800 | static const struct user_regset s390_regsets[] = { | 831 | static 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 | ||
819 | static const struct user_regset_view user_s390_view = { | 859 | static 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 | ||
991 | static 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 | |||
951 | static const struct user_regset s390_compat_regsets[] = { | 1012 | static 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 | ||
381 | give_sigsegv: | 383 | give_sigsegv: |
diff --git a/include/linux/elf.h b/include/linux/elf.h index 597858418051..4d608014753a 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h | |||
@@ -394,6 +394,7 @@ typedef struct elf64_shdr { | |||
394 | #define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ | 394 | #define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ |
395 | #define NT_S390_CTRS 0x304 /* s390 control registers */ | 395 | #define NT_S390_CTRS 0x304 /* s390 control registers */ |
396 | #define NT_S390_PREFIX 0x305 /* s390 prefix register */ | 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 | /* Note header in a PT_NOTE section */ | 400 | /* Note header in a PT_NOTE section */ |