diff options
Diffstat (limited to 'arch/blackfin/kernel/ptrace.c')
-rw-r--r-- | arch/blackfin/kernel/ptrace.c | 155 |
1 files changed, 96 insertions, 59 deletions
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 6a387eec6b65..30f4828277ad 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c | |||
@@ -206,6 +206,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
206 | { | 206 | { |
207 | int ret; | 207 | int ret; |
208 | unsigned long __user *datap = (unsigned long __user *)data; | 208 | unsigned long __user *datap = (unsigned long __user *)data; |
209 | void *paddr = (void *)addr; | ||
209 | 210 | ||
210 | switch (request) { | 211 | switch (request) { |
211 | /* when I and D space are separate, these will need to be fixed. */ | 212 | /* when I and D space are separate, these will need to be fixed. */ |
@@ -215,42 +216,49 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
215 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 216 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
216 | { | 217 | { |
217 | unsigned long tmp = 0; | 218 | unsigned long tmp = 0; |
218 | int copied; | 219 | int copied = 0, to_copy = sizeof(tmp); |
219 | 220 | ||
220 | ret = -EIO; | 221 | ret = -EIO; |
221 | pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %ld\n", addr, sizeof(data)); | 222 | pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %i\n", addr, to_copy); |
222 | if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) | 223 | if (is_user_addr_valid(child, addr, to_copy) < 0) |
223 | break; | 224 | break; |
224 | pr_debug("ptrace: user address is valid\n"); | 225 | pr_debug("ptrace: user address is valid\n"); |
225 | 226 | ||
226 | if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start() | 227 | switch (bfin_mem_access_type(addr, to_copy)) { |
227 | && addr + sizeof(tmp) <= get_l1_code_start() + L1_CODE_LENGTH) { | 228 | case BFIN_MEM_ACCESS_CORE: |
228 | safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); | 229 | case BFIN_MEM_ACCESS_CORE_ONLY: |
229 | copied = sizeof(tmp); | ||
230 | |||
231 | } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START | ||
232 | && addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { | ||
233 | memcpy(&tmp, (const void *)(addr), sizeof(tmp)); | ||
234 | copied = sizeof(tmp); | ||
235 | |||
236 | } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START | ||
237 | && addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { | ||
238 | memcpy(&tmp, (const void *)(addr), sizeof(tmp)); | ||
239 | copied = sizeof(tmp); | ||
240 | |||
241 | } else if (addr >= FIXED_CODE_START | ||
242 | && addr + sizeof(tmp) <= FIXED_CODE_END) { | ||
243 | copy_from_user_page(0, 0, 0, &tmp, (const void *)(addr), sizeof(tmp)); | ||
244 | copied = sizeof(tmp); | ||
245 | |||
246 | } else | ||
247 | copied = access_process_vm(child, addr, &tmp, | 230 | copied = access_process_vm(child, addr, &tmp, |
248 | sizeof(tmp), 0); | 231 | to_copy, 0); |
232 | if (copied) | ||
233 | break; | ||
234 | |||
235 | /* hrm, why didn't that work ... maybe no mapping */ | ||
236 | if (addr >= FIXED_CODE_START && | ||
237 | addr + to_copy <= FIXED_CODE_END) { | ||
238 | copy_from_user_page(0, 0, 0, &tmp, paddr, to_copy); | ||
239 | copied = to_copy; | ||
240 | } else if (addr >= BOOT_ROM_START) { | ||
241 | memcpy(&tmp, paddr, to_copy); | ||
242 | copied = to_copy; | ||
243 | } | ||
249 | 244 | ||
250 | pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); | ||
251 | if (copied != sizeof(tmp)) | ||
252 | break; | 245 | break; |
253 | ret = put_user(tmp, datap); | 246 | case BFIN_MEM_ACCESS_DMA: |
247 | if (safe_dma_memcpy(&tmp, paddr, to_copy)) | ||
248 | copied = to_copy; | ||
249 | break; | ||
250 | case BFIN_MEM_ACCESS_ITEST: | ||
251 | if (isram_memcpy(&tmp, paddr, to_copy)) | ||
252 | copied = to_copy; | ||
253 | break; | ||
254 | default: | ||
255 | copied = 0; | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); | ||
260 | if (copied == to_copy) | ||
261 | ret = put_user(tmp, datap); | ||
254 | break; | 262 | break; |
255 | } | 263 | } |
256 | 264 | ||
@@ -277,9 +285,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
277 | tmp = child->mm->start_data; | 285 | tmp = child->mm->start_data; |
278 | #ifdef CONFIG_BINFMT_ELF_FDPIC | 286 | #ifdef CONFIG_BINFMT_ELF_FDPIC |
279 | } else if (addr == (sizeof(struct pt_regs) + 12)) { | 287 | } else if (addr == (sizeof(struct pt_regs) + 12)) { |
280 | tmp = child->mm->context.exec_fdpic_loadmap; | 288 | goto case_PTRACE_GETFDPIC_EXEC; |
281 | } else if (addr == (sizeof(struct pt_regs) + 16)) { | 289 | } else if (addr == (sizeof(struct pt_regs) + 16)) { |
282 | tmp = child->mm->context.interp_fdpic_loadmap; | 290 | goto case_PTRACE_GETFDPIC_INTERP; |
283 | #endif | 291 | #endif |
284 | } else { | 292 | } else { |
285 | tmp = get_reg(child, addr); | 293 | tmp = get_reg(child, addr); |
@@ -288,49 +296,78 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
288 | break; | 296 | break; |
289 | } | 297 | } |
290 | 298 | ||
299 | #ifdef CONFIG_BINFMT_ELF_FDPIC | ||
300 | case PTRACE_GETFDPIC: { | ||
301 | unsigned long tmp = 0; | ||
302 | |||
303 | switch (addr) { | ||
304 | case_PTRACE_GETFDPIC_EXEC: | ||
305 | case PTRACE_GETFDPIC_EXEC: | ||
306 | tmp = child->mm->context.exec_fdpic_loadmap; | ||
307 | break; | ||
308 | case_PTRACE_GETFDPIC_INTERP: | ||
309 | case PTRACE_GETFDPIC_INTERP: | ||
310 | tmp = child->mm->context.interp_fdpic_loadmap; | ||
311 | break; | ||
312 | default: | ||
313 | break; | ||
314 | } | ||
315 | |||
316 | ret = put_user(tmp, datap); | ||
317 | break; | ||
318 | } | ||
319 | #endif | ||
320 | |||
291 | /* when I and D space are separate, this will have to be fixed. */ | 321 | /* when I and D space are separate, this will have to be fixed. */ |
292 | case PTRACE_POKEDATA: | 322 | case PTRACE_POKEDATA: |
293 | pr_debug("ptrace: PTRACE_PEEKDATA\n"); | 323 | pr_debug("ptrace: PTRACE_PEEKDATA\n"); |
294 | /* fall through */ | 324 | /* fall through */ |
295 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 325 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
296 | { | 326 | { |
297 | int copied; | 327 | int copied = 0, to_copy = sizeof(data); |
298 | 328 | ||
299 | ret = -EIO; | 329 | ret = -EIO; |
300 | pr_debug("ptrace: POKETEXT at addr 0x%08lx + %ld bytes %lx\n", | 330 | pr_debug("ptrace: POKETEXT at addr 0x%08lx + %i bytes %lx\n", |
301 | addr, sizeof(data), data); | 331 | addr, to_copy, data); |
302 | if (is_user_addr_valid(child, addr, sizeof(data)) < 0) | 332 | if (is_user_addr_valid(child, addr, to_copy) < 0) |
303 | break; | 333 | break; |
304 | pr_debug("ptrace: user address is valid\n"); | 334 | pr_debug("ptrace: user address is valid\n"); |
305 | 335 | ||
306 | if (L1_CODE_LENGTH != 0 && addr >= get_l1_code_start() | 336 | switch (bfin_mem_access_type(addr, to_copy)) { |
307 | && addr + sizeof(data) <= get_l1_code_start() + L1_CODE_LENGTH) { | 337 | case BFIN_MEM_ACCESS_CORE: |
308 | safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); | 338 | case BFIN_MEM_ACCESS_CORE_ONLY: |
309 | copied = sizeof(data); | ||
310 | |||
311 | } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START | ||
312 | && addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { | ||
313 | memcpy((void *)(addr), &data, sizeof(data)); | ||
314 | copied = sizeof(data); | ||
315 | |||
316 | } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START | ||
317 | && addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { | ||
318 | memcpy((void *)(addr), &data, sizeof(data)); | ||
319 | copied = sizeof(data); | ||
320 | |||
321 | } else if (addr >= FIXED_CODE_START | ||
322 | && addr + sizeof(data) <= FIXED_CODE_END) { | ||
323 | copy_to_user_page(0, 0, 0, (void *)(addr), &data, sizeof(data)); | ||
324 | copied = sizeof(data); | ||
325 | |||
326 | } else | ||
327 | copied = access_process_vm(child, addr, &data, | 339 | copied = access_process_vm(child, addr, &data, |
328 | sizeof(data), 1); | 340 | to_copy, 0); |
341 | if (copied) | ||
342 | break; | ||
343 | |||
344 | /* hrm, why didn't that work ... maybe no mapping */ | ||
345 | if (addr >= FIXED_CODE_START && | ||
346 | addr + to_copy <= FIXED_CODE_END) { | ||
347 | copy_to_user_page(0, 0, 0, paddr, &data, to_copy); | ||
348 | copied = to_copy; | ||
349 | } else if (addr >= BOOT_ROM_START) { | ||
350 | memcpy(paddr, &data, to_copy); | ||
351 | copied = to_copy; | ||
352 | } | ||
329 | 353 | ||
330 | pr_debug("ptrace: copied size %d\n", copied); | ||
331 | if (copied != sizeof(data)) | ||
332 | break; | 354 | break; |
333 | ret = 0; | 355 | case BFIN_MEM_ACCESS_DMA: |
356 | if (safe_dma_memcpy(paddr, &data, to_copy)) | ||
357 | copied = to_copy; | ||
358 | break; | ||
359 | case BFIN_MEM_ACCESS_ITEST: | ||
360 | if (isram_memcpy(paddr, &data, to_copy)) | ||
361 | copied = to_copy; | ||
362 | break; | ||
363 | default: | ||
364 | copied = 0; | ||
365 | break; | ||
366 | } | ||
367 | |||
368 | pr_debug("ptrace: copied size %d\n", copied); | ||
369 | if (copied == to_copy) | ||
370 | ret = 0; | ||
334 | break; | 371 | break; |
335 | } | 372 | } |
336 | 373 | ||