~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to arch/sh/kernel/ptrace_64.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno, Martin Michlmayr
  • Date: 2011-04-06 13:53:30 UTC
  • mfrom: (43.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110406135330-wjufxhd0tvn3zx4z
Tags: 2.6.38-3
[ Ben Hutchings ]
* [ppc64] Add to linux-tools package architectures (Closes: #620124)
* [amd64] Save cr4 to mmu_cr4_features at boot time (Closes: #620284)
* appletalk: Fix bugs introduced when removing use of BKL
* ALSA: Fix yet another race in disconnection
* cciss: Fix lost command issue
* ath9k: Fix kernel panic in AR2427
* ses: Avoid kernel panic when lun 0 is not mapped
* PCI/ACPI: Report ASPM support to BIOS if not disabled from command line

[ Aurelien Jarno ]
* rtlwifi: fix build when PCI is not enabled.

[ Martin Michlmayr ]
* rtlwifi: Eliminate udelay calls with too large values (Closes: #620204)

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include <linux/sched.h>
21
21
#include <linux/mm.h>
22
22
#include <linux/smp.h>
23
 
#include <linux/smp_lock.h>
 
23
#include <linux/bitops.h>
24
24
#include <linux/errno.h>
25
25
#include <linux/ptrace.h>
26
26
#include <linux/user.h>
82
82
 
83
83
        if (last_task_used_math == task) {
84
84
                enable_fpu();
85
 
                save_fpu(task, regs);
 
85
                save_fpu(task);
86
86
                disable_fpu();
87
87
                last_task_used_math = 0;
88
88
                regs->sr |= SR_FD;
89
89
        }
90
90
 
91
 
        tmp = ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)];
 
91
        tmp = ((long *)task->thread.xstate)[addr / sizeof(unsigned long)];
92
92
        return tmp;
93
93
}
94
94
 
114
114
        regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1;
115
115
 
116
116
        if (!tsk_used_math(task)) {
117
 
                fpinit(&task->thread.fpu.hard);
118
 
                set_stopped_child_used_math(task);
 
117
                init_fpu(task);
119
118
        } else if (last_task_used_math == task) {
120
119
                enable_fpu();
121
 
                save_fpu(task, regs);
 
120
                save_fpu(task);
122
121
                disable_fpu();
123
122
                last_task_used_math = 0;
124
123
                regs->sr |= SR_FD;
125
124
        }
126
125
 
127
 
        ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)] = data;
 
126
        ((long *)task->thread.xstate)[addr / sizeof(unsigned long)] = data;
128
127
        return 0;
129
128
}
130
129
 
133
132
        struct pt_regs *regs = child->thread.uregs;
134
133
 
135
134
        regs->sr |= SR_SSTEP;   /* auto-resetting upon exception */
 
135
 
 
136
        set_tsk_thread_flag(child, TIF_SINGLESTEP);
136
137
}
137
138
 
138
139
void user_disable_single_step(struct task_struct *child)
140
141
        struct pt_regs *regs = child->thread.uregs;
141
142
 
142
143
        regs->sr &= ~SR_SSTEP;
 
144
 
 
145
        clear_tsk_thread_flag(child, TIF_SINGLESTEP);
143
146
}
144
147
 
145
148
static int genregs_get(struct task_struct *target,
222
225
                return ret;
223
226
 
224
227
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
225
 
                                   &target->thread.fpu.hard, 0, -1);
 
228
                                   &target->thread.xstate->hardfpu, 0, -1);
226
229
}
227
230
 
228
231
static int fpregs_set(struct task_struct *target,
239
242
        set_stopped_child_used_math(target);
240
243
 
241
244
        return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
242
 
                                  &target->thread.fpu.hard, 0, -1);
 
245
                                  &target->thread.xstate->hardfpu, 0, -1);
243
246
}
244
247
 
245
248
static int fpregs_active(struct task_struct *target,
249
252
}
250
253
#endif
251
254
 
 
255
const struct pt_regs_offset regoffset_table[] = {
 
256
        REG_OFFSET_NAME(pc),
 
257
        REG_OFFSET_NAME(sr),
 
258
        REG_OFFSET_NAME(syscall_nr),
 
259
        REGS_OFFSET_NAME(0),
 
260
        REGS_OFFSET_NAME(1),
 
261
        REGS_OFFSET_NAME(2),
 
262
        REGS_OFFSET_NAME(3),
 
263
        REGS_OFFSET_NAME(4),
 
264
        REGS_OFFSET_NAME(5),
 
265
        REGS_OFFSET_NAME(6),
 
266
        REGS_OFFSET_NAME(7),
 
267
        REGS_OFFSET_NAME(8),
 
268
        REGS_OFFSET_NAME(9),
 
269
        REGS_OFFSET_NAME(10),
 
270
        REGS_OFFSET_NAME(11),
 
271
        REGS_OFFSET_NAME(12),
 
272
        REGS_OFFSET_NAME(13),
 
273
        REGS_OFFSET_NAME(14),
 
274
        REGS_OFFSET_NAME(15),
 
275
        REGS_OFFSET_NAME(16),
 
276
        REGS_OFFSET_NAME(17),
 
277
        REGS_OFFSET_NAME(18),
 
278
        REGS_OFFSET_NAME(19),
 
279
        REGS_OFFSET_NAME(20),
 
280
        REGS_OFFSET_NAME(21),
 
281
        REGS_OFFSET_NAME(22),
 
282
        REGS_OFFSET_NAME(23),
 
283
        REGS_OFFSET_NAME(24),
 
284
        REGS_OFFSET_NAME(25),
 
285
        REGS_OFFSET_NAME(26),
 
286
        REGS_OFFSET_NAME(27),
 
287
        REGS_OFFSET_NAME(28),
 
288
        REGS_OFFSET_NAME(29),
 
289
        REGS_OFFSET_NAME(30),
 
290
        REGS_OFFSET_NAME(31),
 
291
        REGS_OFFSET_NAME(32),
 
292
        REGS_OFFSET_NAME(33),
 
293
        REGS_OFFSET_NAME(34),
 
294
        REGS_OFFSET_NAME(35),
 
295
        REGS_OFFSET_NAME(36),
 
296
        REGS_OFFSET_NAME(37),
 
297
        REGS_OFFSET_NAME(38),
 
298
        REGS_OFFSET_NAME(39),
 
299
        REGS_OFFSET_NAME(40),
 
300
        REGS_OFFSET_NAME(41),
 
301
        REGS_OFFSET_NAME(42),
 
302
        REGS_OFFSET_NAME(43),
 
303
        REGS_OFFSET_NAME(44),
 
304
        REGS_OFFSET_NAME(45),
 
305
        REGS_OFFSET_NAME(46),
 
306
        REGS_OFFSET_NAME(47),
 
307
        REGS_OFFSET_NAME(48),
 
308
        REGS_OFFSET_NAME(49),
 
309
        REGS_OFFSET_NAME(50),
 
310
        REGS_OFFSET_NAME(51),
 
311
        REGS_OFFSET_NAME(52),
 
312
        REGS_OFFSET_NAME(53),
 
313
        REGS_OFFSET_NAME(54),
 
314
        REGS_OFFSET_NAME(55),
 
315
        REGS_OFFSET_NAME(56),
 
316
        REGS_OFFSET_NAME(57),
 
317
        REGS_OFFSET_NAME(58),
 
318
        REGS_OFFSET_NAME(59),
 
319
        REGS_OFFSET_NAME(60),
 
320
        REGS_OFFSET_NAME(61),
 
321
        REGS_OFFSET_NAME(62),
 
322
        REGS_OFFSET_NAME(63),
 
323
        TREGS_OFFSET_NAME(0),
 
324
        TREGS_OFFSET_NAME(1),
 
325
        TREGS_OFFSET_NAME(2),
 
326
        TREGS_OFFSET_NAME(3),
 
327
        TREGS_OFFSET_NAME(4),
 
328
        TREGS_OFFSET_NAME(5),
 
329
        TREGS_OFFSET_NAME(6),
 
330
        TREGS_OFFSET_NAME(7),
 
331
        REG_OFFSET_END,
 
332
};
 
333
 
252
334
/*
253
335
 * These are our native regset flavours.
254
336
 */
301
383
        return &user_sh64_native_view;
302
384
}
303
385
 
304
 
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
386
long arch_ptrace(struct task_struct *child, long request,
 
387
                 unsigned long addr, unsigned long data)
305
388
{
306
389
        int ret;
 
390
        unsigned long __user *datap = (unsigned long __user *) data;
307
391
 
308
392
        switch (request) {
309
393
        /* read the word at location addr in the USER area. */
318
402
                        tmp = get_stack_long(child, addr);
319
403
                else if ((addr >= offsetof(struct user, fpu)) &&
320
404
                         (addr <  offsetof(struct user, u_fpvalid))) {
321
 
                        tmp = get_fpu_long(child, addr - offsetof(struct user, fpu));
 
405
                        unsigned long index;
 
406
                        index = addr - offsetof(struct user, fpu);
 
407
                        tmp = get_fpu_long(child, index);
322
408
                } else if (addr == offsetof(struct user, u_fpvalid)) {
323
409
                        tmp = !!tsk_used_math(child);
324
410
                } else {
325
411
                        break;
326
412
                }
327
 
                ret = put_user(tmp, (unsigned long *)data);
 
413
                ret = put_user(tmp, datap);
328
414
                break;
329
415
        }
330
416
 
355
441
                }
356
442
                else if ((addr >= offsetof(struct user, fpu)) &&
357
443
                         (addr <  offsetof(struct user, u_fpvalid))) {
358
 
                        ret = put_fpu_long(child, addr - offsetof(struct user, fpu), data);
 
444
                        unsigned long index;
 
445
                        index = addr - offsetof(struct user, fpu);
 
446
                        ret = put_fpu_long(child, index, data);
359
447
                }
360
448
                break;
361
449
 
363
451
                return copy_regset_to_user(child, &user_sh64_native_view,
364
452
                                           REGSET_GENERAL,
365
453
                                           0, sizeof(struct pt_regs),
366
 
                                           (void __user *)data);
 
454
                                           datap);
367
455
        case PTRACE_SETREGS:
368
456
                return copy_regset_from_user(child, &user_sh64_native_view,
369
457
                                             REGSET_GENERAL,
370
458
                                             0, sizeof(struct pt_regs),
371
 
                                             (const void __user *)data);
 
459
                                             datap);
372
460
#ifdef CONFIG_SH_FPU
373
461
        case PTRACE_GETFPREGS:
374
462
                return copy_regset_to_user(child, &user_sh64_native_view,
375
463
                                           REGSET_FPU,
376
464
                                           0, sizeof(struct user_fpu_struct),
377
 
                                           (void __user *)data);
 
465
                                           datap);
378
466
        case PTRACE_SETFPREGS:
379
467
                return copy_regset_from_user(child, &user_sh64_native_view,
380
468
                                             REGSET_FPU,
381
469
                                             0, sizeof(struct user_fpu_struct),
382
 
                                             (const void __user *)data);
 
470
                                             datap);
383
471
#endif
384
472
        default:
385
473
                ret = ptrace_request(child, request, addr, data);
389
477
        return ret;
390
478
}
391
479
 
392
 
asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
 
480
asmlinkage int sh64_ptrace(long request, long pid,
 
481
                           unsigned long addr, unsigned long data)
393
482
{
394
483
#define WPC_DBRMODE 0x0d104008
395
 
        static int first_call = 1;
 
484
        static unsigned long first_call;
396
485
 
397
 
        lock_kernel();
398
 
        if (first_call) {
 
486
        if (!test_and_set_bit(0, &first_call)) {
399
487
                /* Set WPC.DBRMODE to 0.  This makes all debug events get
400
488
                 * delivered through RESVEC, i.e. into the handlers in entry.S.
401
489
                 * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
405
493
                 * the remote gdb.) */
406
494
                printk("DBRMODE set to 0 to permit native debugging\n");
407
495
                poke_real_address_q(WPC_DBRMODE, 0);
408
 
                first_call = 0;
409
496
        }
410
 
        unlock_kernel();
411
497
 
412
498
        return sys_ptrace(request, pid, addr, data);
413
499
}
454
540
 
455
541
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
456
542
{
 
543
        int step;
 
544
 
457
545
        if (unlikely(current->audit_context))
458
546
                audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]),
459
547
                                   regs->regs[9]);
461
549
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
462
550
                trace_sys_exit(regs, regs->regs[9]);
463
551
 
464
 
        if (test_thread_flag(TIF_SYSCALL_TRACE))
465
 
                tracehook_report_syscall_exit(regs, 0);
 
552
        step = test_thread_flag(TIF_SINGLESTEP);
 
553
        if (step || test_thread_flag(TIF_SYSCALL_TRACE))
 
554
                tracehook_report_syscall_exit(regs, step);
466
555
}
467
556
 
468
557
/* Called with interrupts disabled */
479
568
}
480
569
 
481
570
/* Called with interrupts disabled */
482
 
asmlinkage void do_software_break_point(unsigned long long vec,
483
 
                                        struct pt_regs *regs)
 
571
BUILD_TRAP_HANDLER(breakpoint)
484
572
{
 
573
        TRAP_HANDLER_DECL;
 
574
 
485
575
        /* We need to forward step the PC, to counteract the backstep done
486
576
           in signal.c. */
487
577
        local_irq_enable();