diff options
author | Andreas Schwab <schwab@linux-m68k.org> | 2009-05-10 15:14:52 -0400 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2009-12-04 15:22:35 -0500 |
commit | faa47b466935e73251b18b17d51455b06ed65764 (patch) | |
tree | 0b4618676fa11f566e7f5a7b802fbe985b74492c | |
parent | 4f672ce298e1b53a2f16571ef87810d0f73bfb1f (diff) |
m68k: use generic code for ptrace requests
Remove all but PTRACE_{PEEK,POKE}USR and PTRACE_{GET,SET}{REGS,FPREGS}
from arch_ptrace and let the rest be handled by generic code. Define
PTRACE_SINGLEBLOCK to enable singleblock tracing.
[Geert] Not yet applicable for m68knommu
Signed-off-by: Andreas Schwab <schwab@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-rw-r--r-- | arch/m68k/include/asm/ptrace.h | 17 | ||||
-rw-r--r-- | arch/m68k/kernel/ptrace.c | 75 |
2 files changed, 38 insertions, 54 deletions
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h index 8c9194b98548..117adb1e4806 100644 --- a/arch/m68k/include/asm/ptrace.h +++ b/arch/m68k/include/asm/ptrace.h | |||
@@ -71,6 +71,8 @@ struct switch_stack { | |||
71 | #define PTRACE_GETFPREGS 14 | 71 | #define PTRACE_GETFPREGS 14 |
72 | #define PTRACE_SETFPREGS 15 | 72 | #define PTRACE_SETFPREGS 15 |
73 | 73 | ||
74 | #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ | ||
75 | |||
74 | #ifdef __KERNEL__ | 76 | #ifdef __KERNEL__ |
75 | 77 | ||
76 | #ifndef PS_S | 78 | #ifndef PS_S |
@@ -82,6 +84,21 @@ struct switch_stack { | |||
82 | #define instruction_pointer(regs) ((regs)->pc) | 84 | #define instruction_pointer(regs) ((regs)->pc) |
83 | #define profile_pc(regs) instruction_pointer(regs) | 85 | #define profile_pc(regs) instruction_pointer(regs) |
84 | extern void show_regs(struct pt_regs *); | 86 | extern void show_regs(struct pt_regs *); |
87 | |||
88 | /* | ||
89 | * These are defined as per linux/ptrace.h, which see. | ||
90 | */ | ||
91 | struct task_struct; | ||
92 | |||
93 | #ifdef CONFIG_MMU | ||
94 | #define arch_has_single_step() (1) | ||
95 | extern void user_enable_single_step(struct task_struct *); | ||
96 | extern void user_disable_single_step(struct task_struct *); | ||
97 | |||
98 | #define arch_has_block_step() (1) | ||
99 | extern void user_enable_block_step(struct task_struct *); | ||
100 | #endif | ||
101 | |||
85 | #endif /* __KERNEL__ */ | 102 | #endif /* __KERNEL__ */ |
86 | #endif /* __ASSEMBLY__ */ | 103 | #endif /* __ASSEMBLY__ */ |
87 | #endif /* _M68K_PTRACE_H */ | 104 | #endif /* _M68K_PTRACE_H */ |
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 2075543c2d92..bd0842059d11 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
@@ -35,7 +35,9 @@ | |||
35 | #define SR_MASK 0x001f | 35 | #define SR_MASK 0x001f |
36 | 36 | ||
37 | /* sets the trace bits. */ | 37 | /* sets the trace bits. */ |
38 | #define TRACE_BITS 0x8000 | 38 | #define TRACE_BITS 0xC000 |
39 | #define T1_BIT 0x8000 | ||
40 | #define T0_BIT 0x4000 | ||
39 | 41 | ||
40 | /* Find the stack offset for a register, relative to thread.esp0. */ | 42 | /* Find the stack offset for a register, relative to thread.esp0. */ |
41 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) | 43 | #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) |
@@ -118,18 +120,30 @@ void ptrace_disable(struct task_struct *child) | |||
118 | singlestep_disable(child); | 120 | singlestep_disable(child); |
119 | } | 121 | } |
120 | 122 | ||
123 | void user_enable_single_step(struct task_struct *child) | ||
124 | { | ||
125 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | ||
126 | put_reg(child, PT_SR, tmp | (T1_BIT << 16)); | ||
127 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); | ||
128 | } | ||
129 | |||
130 | void user_enable_block_step(struct task_struct *child) | ||
131 | { | ||
132 | unsigned long tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); | ||
133 | put_reg(child, PT_SR, tmp | (T0_BIT << 16)); | ||
134 | } | ||
135 | |||
136 | void user_disable_single_step(struct task_struct *child) | ||
137 | { | ||
138 | singlestep_disable(child); | ||
139 | } | ||
140 | |||
121 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 141 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
122 | { | 142 | { |
123 | unsigned long tmp; | 143 | unsigned long tmp; |
124 | int i, ret = 0; | 144 | int i, ret = 0; |
125 | 145 | ||
126 | switch (request) { | 146 | switch (request) { |
127 | /* when I and D space are separate, these will need to be fixed. */ | ||
128 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
129 | case PTRACE_PEEKDATA: | ||
130 | ret = generic_ptrace_peekdata(child, addr, data); | ||
131 | break; | ||
132 | |||
133 | /* read the word at location addr in the USER area. */ | 147 | /* read the word at location addr in the USER area. */ |
134 | case PTRACE_PEEKUSR: | 148 | case PTRACE_PEEKUSR: |
135 | if (addr & 3) | 149 | if (addr & 3) |
@@ -153,12 +167,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
153 | ret = put_user(tmp, (unsigned long *)data); | 167 | ret = put_user(tmp, (unsigned long *)data); |
154 | break; | 168 | break; |
155 | 169 | ||
156 | /* when I and D space are separate, this will have to be fixed. */ | ||
157 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
158 | case PTRACE_POKEDATA: | ||
159 | ret = generic_ptrace_pokedata(child, addr, data); | ||
160 | break; | ||
161 | |||
162 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 170 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
163 | if (addr & 3) | 171 | if (addr & 3) |
164 | goto out_eio; | 172 | goto out_eio; |
@@ -185,47 +193,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
185 | goto out_eio; | 193 | goto out_eio; |
186 | break; | 194 | break; |
187 | 195 | ||
188 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
189 | case PTRACE_CONT: /* restart after signal. */ | ||
190 | if (!valid_signal(data)) | ||
191 | goto out_eio; | ||
192 | |||
193 | if (request == PTRACE_SYSCALL) | ||
194 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
195 | else | ||
196 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
197 | child->exit_code = data; | ||
198 | singlestep_disable(child); | ||
199 | wake_up_process(child); | ||
200 | break; | ||
201 | |||
202 | /* | ||
203 | * make the child exit. Best I can do is send it a sigkill. | ||
204 | * perhaps it should be put in the status that it wants to | ||
205 | * exit. | ||
206 | */ | ||
207 | case PTRACE_KILL: | ||
208 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
209 | break; | ||
210 | child->exit_code = SIGKILL; | ||
211 | singlestep_disable(child); | ||
212 | wake_up_process(child); | ||
213 | break; | ||
214 | |||
215 | case PTRACE_SINGLESTEP: /* set the trap flag. */ | ||
216 | if (!valid_signal(data)) | ||
217 | goto out_eio; | ||
218 | |||
219 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
220 | tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); | ||
221 | put_reg(child, PT_SR, tmp); | ||
222 | set_tsk_thread_flag(child, TIF_DELAYED_TRACE); | ||
223 | |||
224 | child->exit_code = data; | ||
225 | /* give it a chance to run. */ | ||
226 | wake_up_process(child); | ||
227 | break; | ||
228 | |||
229 | case PTRACE_GETREGS: /* Get all gp regs from the child. */ | 196 | case PTRACE_GETREGS: /* Get all gp regs from the child. */ |
230 | for (i = 0; i < 19; i++) { | 197 | for (i = 0; i < 19; i++) { |
231 | tmp = get_reg(child, i); | 198 | tmp = get_reg(child, i); |