aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/ptrace.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2011-01-05 06:48:10 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2011-01-05 06:47:31 -0500
commit5e9a26928f550157563cfc06ce12c4ae121a02ec (patch)
treefc58668f8c6151a5f58c0430f92a0691d727af42 /arch/s390/kernel/ptrace.c
parentda7f51c11d5fedca9ba779ee220063ccb4f0a27e (diff)
[S390] ptrace cleanup
Overhaul program event recording and the code dealing with the ptrace user space interface. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/ptrace.c')
-rw-r--r--arch/s390/kernel/ptrace.c306
1 files changed, 187 insertions, 119 deletions
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 019bb714db49..ef86ad243986 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -1,25 +1,9 @@
1/* 1/*
2 * arch/s390/kernel/ptrace.c 2 * Ptrace user space interface.
3 * 3 *
4 * S390 version 4 * Copyright IBM Corp. 1999,2010
5 * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation 5 * Author(s): Denis Joseph Barrow
6 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
7 * Martin Schwidefsky (schwidefsky@de.ibm.com) 6 * Martin Schwidefsky (schwidefsky@de.ibm.com)
8 *
9 * Based on PowerPC version
10 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
11 *
12 * Derived from "arch/m68k/kernel/ptrace.c"
13 * Copyright (C) 1994 by Hamish Macdonald
14 * Taken from linux/kernel/ptrace.c and modified for M680x0.
15 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
16 *
17 * Modified by Cort Dougan (cort@cs.nmt.edu)
18 *
19 *
20 * This file is subject to the terms and conditions of the GNU General
21 * Public License. See the file README.legal in the main directory of
22 * this archive for more details.
23 */ 7 */
24 8
25#include <linux/kernel.h> 9#include <linux/kernel.h>
@@ -61,76 +45,58 @@ enum s390_regset {
61 REGSET_GENERAL_EXTENDED, 45 REGSET_GENERAL_EXTENDED,
62}; 46};
63 47
64static void 48void update_per_regs(struct task_struct *task)
65FixPerRegisters(struct task_struct *task)
66{ 49{
67 struct pt_regs *regs; 50 static const struct per_regs per_single_step = {
68 per_struct *per_info; 51 .control = PER_EVENT_IFETCH,
69 per_cr_words cr_words; 52 .start = 0,
70 53 .end = PSW_ADDR_INSN,
71 regs = task_pt_regs(task); 54 };
72 per_info = (per_struct *) &task->thread.per_info; 55 struct pt_regs *regs = task_pt_regs(task);
73 per_info->control_regs.bits.em_instruction_fetch = 56 struct thread_struct *thread = &task->thread;
74 per_info->single_step | per_info->instruction_fetch; 57 const struct per_regs *new;
75 58 struct per_regs old;
76 if (per_info->single_step) { 59
77 per_info->control_regs.bits.starting_addr = 0; 60 /* TIF_SINGLE_STEP overrides the user specified PER registers. */
78#ifdef CONFIG_COMPAT 61 new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ?
79 if (is_compat_task()) 62 &per_single_step : &thread->per_user;
80 per_info->control_regs.bits.ending_addr = 0x7fffffffUL; 63
81 else 64 /* Take care of the PER enablement bit in the PSW. */
82#endif 65 if (!(new->control & PER_EVENT_MASK)) {
83 per_info->control_regs.bits.ending_addr = PSW_ADDR_INSN;
84 } else {
85 per_info->control_regs.bits.starting_addr =
86 per_info->starting_addr;
87 per_info->control_regs.bits.ending_addr =
88 per_info->ending_addr;
89 }
90 /*
91 * if any of the control reg tracing bits are on
92 * we switch on per in the psw
93 */
94 if (per_info->control_regs.words.cr[0] & PER_EM_MASK)
95 regs->psw.mask |= PSW_MASK_PER;
96 else
97 regs->psw.mask &= ~PSW_MASK_PER; 66 regs->psw.mask &= ~PSW_MASK_PER;
98 67 return;
99 if (per_info->control_regs.bits.em_storage_alteration)
100 per_info->control_regs.bits.storage_alt_space_ctl = 1;
101 else
102 per_info->control_regs.bits.storage_alt_space_ctl = 0;
103
104 if (task == current) {
105 __ctl_store(cr_words, 9, 11);
106 if (memcmp(&cr_words, &per_info->control_regs.words,
107 sizeof(cr_words)) != 0)
108 __ctl_load(per_info->control_regs.words, 9, 11);
109 } 68 }
69 regs->psw.mask |= PSW_MASK_PER;
70 __ctl_store(old, 9, 11);
71 if (memcmp(new, &old, sizeof(struct per_regs)) != 0)
72 __ctl_load(*new, 9, 11);
110} 73}
111 74
112void user_enable_single_step(struct task_struct *task) 75void user_enable_single_step(struct task_struct *task)
113{ 76{
114 task->thread.per_info.single_step = 1; 77 set_tsk_thread_flag(task, TIF_SINGLE_STEP);
115 FixPerRegisters(task); 78 if (task == current)
79 update_per_regs(task);
116} 80}
117 81
118void user_disable_single_step(struct task_struct *task) 82void user_disable_single_step(struct task_struct *task)
119{ 83{
120 task->thread.per_info.single_step = 0; 84 clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
121 FixPerRegisters(task); 85 if (task == current)
86 update_per_regs(task);
122} 87}
123 88
124/* 89/*
125 * Called by kernel/ptrace.c when detaching.. 90 * Called by kernel/ptrace.c when detaching..
126 * 91 *
127 * Make sure single step bits etc are not set. 92 * Clear all debugging related fields.
128 */ 93 */
129void 94void ptrace_disable(struct task_struct *task)
130ptrace_disable(struct task_struct *child)
131{ 95{
132 /* make sure the single step bit is not set. */ 96 memset(&task->thread.per_user, 0, sizeof(task->thread.per_user));
133 user_disable_single_step(child); 97 memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));
98 clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
99 clear_tsk_thread_flag(task, TIF_PER_TRAP);
134} 100}
135 101
136#ifndef CONFIG_64BIT 102#ifndef CONFIG_64BIT
@@ -139,6 +105,47 @@ ptrace_disable(struct task_struct *child)
139# define __ADDR_MASK 7 105# define __ADDR_MASK 7
140#endif 106#endif
141 107
108static inline unsigned long __peek_user_per(struct task_struct *child,
109 addr_t addr)
110{
111 struct per_struct_kernel *dummy = NULL;
112
113 if (addr == (addr_t) &dummy->cr9)
114 /* Control bits of the active per set. */
115 return test_thread_flag(TIF_SINGLE_STEP) ?
116 PER_EVENT_IFETCH : child->thread.per_user.control;
117 else if (addr == (addr_t) &dummy->cr10)
118 /* Start address of the active per set. */
119 return test_thread_flag(TIF_SINGLE_STEP) ?
120 0 : child->thread.per_user.start;
121 else if (addr == (addr_t) &dummy->cr11)
122 /* End address of the active per set. */
123 return test_thread_flag(TIF_SINGLE_STEP) ?
124 PSW_ADDR_INSN : child->thread.per_user.end;
125 else if (addr == (addr_t) &dummy->bits)
126 /* Single-step bit. */
127 return test_thread_flag(TIF_SINGLE_STEP) ?
128 (1UL << (BITS_PER_LONG - 1)) : 0;
129 else if (addr == (addr_t) &dummy->starting_addr)
130 /* Start address of the user specified per set. */
131 return child->thread.per_user.start;
132 else if (addr == (addr_t) &dummy->ending_addr)
133 /* End address of the user specified per set. */
134 return child->thread.per_user.end;
135 else if (addr == (addr_t) &dummy->perc_atmid)
136 /* PER code, ATMID and AI of the last PER trap */
137 return (unsigned long)
138 child->thread.per_event.cause << (BITS_PER_LONG - 16);
139 else if (addr == (addr_t) &dummy->address)
140 /* Address of the last PER trap */
141 return child->thread.per_event.address;
142 else if (addr == (addr_t) &dummy->access_id)
143 /* Access id of the last PER trap */
144 return (unsigned long)
145 child->thread.per_event.paid << (BITS_PER_LONG - 8);
146 return 0;
147}
148
142/* 149/*
143 * Read the word at offset addr from the user area of a process. The 150 * Read the word at offset addr from the user area of a process. The
144 * trouble here is that the information is littered over different 151 * trouble here is that the information is littered over different
@@ -204,10 +211,10 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
204 211
205 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { 212 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
206 /* 213 /*
207 * per_info is found in the thread structure 214 * Handle access to the per_info structure.
208 */ 215 */
209 offset = addr - (addr_t) &dummy->regs.per_info; 216 addr -= (addr_t) &dummy->regs.per_info;
210 tmp = *(addr_t *)((addr_t) &child->thread.per_info + offset); 217 tmp = __peek_user_per(child, addr);
211 218
212 } else 219 } else
213 tmp = 0; 220 tmp = 0;
@@ -237,6 +244,35 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
237 return put_user(tmp, (addr_t __user *) data); 244 return put_user(tmp, (addr_t __user *) data);
238} 245}
239 246
247static inline void __poke_user_per(struct task_struct *child,
248 addr_t addr, addr_t data)
249{
250 struct per_struct_kernel *dummy = NULL;
251
252 /*
253 * There are only three fields in the per_info struct that the
254 * debugger user can write to.
255 * 1) cr9: the debugger wants to set a new PER event mask
256 * 2) starting_addr: the debugger wants to set a new starting
257 * address to use with the PER event mask.
258 * 3) ending_addr: the debugger wants to set a new ending
259 * address to use with the PER event mask.
260 * The user specified PER event mask and the start and end
261 * addresses are used only if single stepping is not in effect.
262 * Writes to any other field in per_info are ignored.
263 */
264 if (addr == (addr_t) &dummy->cr9)
265 /* PER event mask of the user specified per set. */
266 child->thread.per_user.control =
267 data & (PER_EVENT_MASK | PER_CONTROL_MASK);
268 else if (addr == (addr_t) &dummy->starting_addr)
269 /* Starting address of the user specified per set. */
270 child->thread.per_user.start = data;
271 else if (addr == (addr_t) &dummy->ending_addr)
272 /* Ending address of the user specified per set. */
273 child->thread.per_user.end = data;
274}
275
240/* 276/*
241 * Write a word to the user area of a process at location addr. This 277 * Write a word to the user area of a process at location addr. This
242 * operation does have an additional problem compared to peek_user. 278 * operation does have an additional problem compared to peek_user.
@@ -311,19 +347,17 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
311 347
312 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) { 348 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
313 /* 349 /*
314 * per_info is found in the thread structure 350 * Handle access to the per_info structure.
315 */ 351 */
316 offset = addr - (addr_t) &dummy->regs.per_info; 352 addr -= (addr_t) &dummy->regs.per_info;
317 *(addr_t *)((addr_t) &child->thread.per_info + offset) = data; 353 __poke_user_per(child, addr, data);
318 354
319 } 355 }
320 356
321 FixPerRegisters(child);
322 return 0; 357 return 0;
323} 358}
324 359
325static int 360static int poke_user(struct task_struct *child, addr_t addr, addr_t data)
326poke_user(struct task_struct *child, addr_t addr, addr_t data)
327{ 361{
328 addr_t mask; 362 addr_t mask;
329 363
@@ -410,12 +444,53 @@ long arch_ptrace(struct task_struct *child, long request,
410 */ 444 */
411 445
412/* 446/*
447 * Same as peek_user_per but for a 31 bit program.
448 */
449static inline __u32 __peek_user_per_compat(struct task_struct *child,
450 addr_t addr)
451{
452 struct compat_per_struct_kernel *dummy32 = NULL;
453
454 if (addr == (addr_t) &dummy32->cr9)
455 /* Control bits of the active per set. */
456 return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?
457 PER_EVENT_IFETCH : child->thread.per_user.control;
458 else if (addr == (addr_t) &dummy32->cr10)
459 /* Start address of the active per set. */
460 return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?
461 0 : child->thread.per_user.start;
462 else if (addr == (addr_t) &dummy32->cr11)
463 /* End address of the active per set. */
464 return test_thread_flag(TIF_SINGLE_STEP) ?
465 PSW32_ADDR_INSN : child->thread.per_user.end;
466 else if (addr == (addr_t) &dummy32->bits)
467 /* Single-step bit. */
468 return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?
469 0x80000000 : 0;
470 else if (addr == (addr_t) &dummy32->starting_addr)
471 /* Start address of the user specified per set. */
472 return (__u32) child->thread.per_user.start;
473 else if (addr == (addr_t) &dummy32->ending_addr)
474 /* End address of the user specified per set. */
475 return (__u32) child->thread.per_user.end;
476 else if (addr == (addr_t) &dummy32->perc_atmid)
477 /* PER code, ATMID and AI of the last PER trap */
478 return (__u32) child->thread.per_event.cause << 16;
479 else if (addr == (addr_t) &dummy32->address)
480 /* Address of the last PER trap */
481 return (__u32) child->thread.per_event.address;
482 else if (addr == (addr_t) &dummy32->access_id)
483 /* Access id of the last PER trap */
484 return (__u32) child->thread.per_event.paid << 24;
485 return 0;
486}
487
488/*
413 * Same as peek_user but for a 31 bit program. 489 * Same as peek_user but for a 31 bit program.
414 */ 490 */
415static u32 __peek_user_compat(struct task_struct *child, addr_t addr) 491static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
416{ 492{
417 struct user32 *dummy32 = NULL; 493 struct compat_user *dummy32 = NULL;
418 per_struct32 *dummy_per32 = NULL;
419 addr_t offset; 494 addr_t offset;
420 __u32 tmp; 495 __u32 tmp;
421 496
@@ -465,19 +540,10 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
465 540
466 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { 541 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
467 /* 542 /*
468 * per_info is found in the thread structure 543 * Handle access to the per_info structure.
469 */ 544 */
470 offset = addr - (addr_t) &dummy32->regs.per_info; 545 addr -= (addr_t) &dummy32->regs.per_info;
471 /* This is magic. See per_struct and per_struct32. */ 546 tmp = __peek_user_per_compat(child, addr);
472 if ((offset >= (addr_t) &dummy_per32->control_regs &&
473 offset < (addr_t) (&dummy_per32->control_regs + 1)) ||
474 (offset >= (addr_t) &dummy_per32->starting_addr &&
475 offset <= (addr_t) &dummy_per32->ending_addr) ||
476 offset == (addr_t) &dummy_per32->lowcore.words.address)
477 offset = offset*2 + 4;
478 else
479 offset = offset*2;
480 tmp = *(__u32 *)((addr_t) &child->thread.per_info + offset);
481 547
482 } else 548 } else
483 tmp = 0; 549 tmp = 0;
@@ -498,13 +564,32 @@ static int peek_user_compat(struct task_struct *child,
498} 564}
499 565
500/* 566/*
567 * Same as poke_user_per but for a 31 bit program.
568 */
569static inline void __poke_user_per_compat(struct task_struct *child,
570 addr_t addr, __u32 data)
571{
572 struct compat_per_struct_kernel *dummy32 = NULL;
573
574 if (addr == (addr_t) &dummy32->cr9)
575 /* PER event mask of the user specified per set. */
576 child->thread.per_user.control =
577 data & (PER_EVENT_MASK | PER_CONTROL_MASK);
578 else if (addr == (addr_t) &dummy32->starting_addr)
579 /* Starting address of the user specified per set. */
580 child->thread.per_user.start = data;
581 else if (addr == (addr_t) &dummy32->ending_addr)
582 /* Ending address of the user specified per set. */
583 child->thread.per_user.end = data;
584}
585
586/*
501 * Same as poke_user but for a 31 bit program. 587 * Same as poke_user but for a 31 bit program.
502 */ 588 */
503static int __poke_user_compat(struct task_struct *child, 589static int __poke_user_compat(struct task_struct *child,
504 addr_t addr, addr_t data) 590 addr_t addr, addr_t data)
505{ 591{
506 struct user32 *dummy32 = NULL; 592 struct compat_user *dummy32 = NULL;
507 per_struct32 *dummy_per32 = NULL;
508 __u32 tmp = (__u32) data; 593 __u32 tmp = (__u32) data;
509 addr_t offset; 594 addr_t offset;
510 595
@@ -561,37 +646,20 @@ static int __poke_user_compat(struct task_struct *child,
561 646
562 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) { 647 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {
563 /* 648 /*
564 * per_info is found in the thread structure. 649 * Handle access to the per_info structure.
565 */
566 offset = addr - (addr_t) &dummy32->regs.per_info;
567 /*
568 * This is magic. See per_struct and per_struct32.
569 * By incident the offsets in per_struct are exactly
570 * twice the offsets in per_struct32 for all fields.
571 * The 8 byte fields need special handling though,
572 * because the second half (bytes 4-7) is needed and
573 * not the first half.
574 */ 650 */
575 if ((offset >= (addr_t) &dummy_per32->control_regs && 651 addr -= (addr_t) &dummy32->regs.per_info;
576 offset < (addr_t) (&dummy_per32->control_regs + 1)) || 652 __poke_user_per_compat(child, addr, data);
577 (offset >= (addr_t) &dummy_per32->starting_addr &&
578 offset <= (addr_t) &dummy_per32->ending_addr) ||
579 offset == (addr_t) &dummy_per32->lowcore.words.address)
580 offset = offset*2 + 4;
581 else
582 offset = offset*2;
583 *(__u32 *)((addr_t) &child->thread.per_info + offset) = tmp;
584
585 } 653 }
586 654
587 FixPerRegisters(child);
588 return 0; 655 return 0;
589} 656}
590 657
591static int poke_user_compat(struct task_struct *child, 658static int poke_user_compat(struct task_struct *child,
592 addr_t addr, addr_t data) 659 addr_t addr, addr_t data)
593{ 660{
594 if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user32) - 3) 661 if (!is_compat_task() || (addr & 3) ||
662 addr > sizeof(struct compat_user) - 3)
595 return -EIO; 663 return -EIO;
596 664
597 return __poke_user_compat(child, addr, data); 665 return __poke_user_compat(child, addr, data);
@@ -602,7 +670,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
602{ 670{
603 unsigned long addr = caddr; 671 unsigned long addr = caddr;
604 unsigned long data = cdata; 672 unsigned long data = cdata;
605 ptrace_area_emu31 parea; 673 compat_ptrace_area parea;
606 int copied, ret; 674 int copied, ret;
607 675
608 switch (request) { 676 switch (request) {