diff options
Diffstat (limited to 'arch/sh/kernel')
| -rw-r--r-- | arch/sh/kernel/cpu/clock.c | 4 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S | 3 | ||||
| -rw-r--r-- | arch/sh/kernel/dwarf.c | 28 | ||||
| -rw-r--r-- | arch/sh/kernel/entry-common.S | 8 | ||||
| -rw-r--r-- | arch/sh/kernel/process_64.c | 2 | ||||
| -rw-r--r-- | arch/sh/kernel/ptrace_64.c | 11 | ||||
| -rw-r--r-- | arch/sh/kernel/signal_64.c | 4 | ||||
| -rw-r--r-- | arch/sh/kernel/syscalls_32.S | 1 | ||||
| -rw-r--r-- | arch/sh/kernel/syscalls_64.S | 1 |
9 files changed, 49 insertions, 13 deletions
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index f3a46be2ae81..83da5debeedf 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c | |||
| @@ -598,7 +598,7 @@ static struct dentry *clk_debugfs_root; | |||
| 598 | static int clk_debugfs_register_one(struct clk *c) | 598 | static int clk_debugfs_register_one(struct clk *c) |
| 599 | { | 599 | { |
| 600 | int err; | 600 | int err; |
| 601 | struct dentry *d, *child; | 601 | struct dentry *d, *child, *child_tmp; |
| 602 | struct clk *pa = c->parent; | 602 | struct clk *pa = c->parent; |
| 603 | char s[255]; | 603 | char s[255]; |
| 604 | char *p = s; | 604 | char *p = s; |
| @@ -630,7 +630,7 @@ static int clk_debugfs_register_one(struct clk *c) | |||
| 630 | 630 | ||
| 631 | err_out: | 631 | err_out: |
| 632 | d = c->dentry; | 632 | d = c->dentry; |
| 633 | list_for_each_entry(child, &d->d_subdirs, d_u.d_child) | 633 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) |
| 634 | debugfs_remove(child); | 634 | debugfs_remove(child); |
| 635 | debugfs_remove(c->dentry); | 635 | debugfs_remove(c->dentry); |
| 636 | return err; | 636 | return err; |
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 3f7e2a22c7c2..f6a389c996cb 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
| @@ -132,7 +132,6 @@ ENTRY(tlb_protection_violation_store) | |||
| 132 | mov #1, r5 | 132 | mov #1, r5 |
| 133 | 133 | ||
| 134 | call_handle_tlbmiss: | 134 | call_handle_tlbmiss: |
| 135 | setup_frame_reg | ||
| 136 | mov.l 1f, r0 | 135 | mov.l 1f, r0 |
| 137 | mov r5, r8 | 136 | mov r5, r8 |
| 138 | mov.l @r0, r6 | 137 | mov.l @r0, r6 |
| @@ -365,6 +364,8 @@ handle_exception: | |||
| 365 | mov.l @k2, k2 ! read out vector and keep in k2 | 364 | mov.l @k2, k2 ! read out vector and keep in k2 |
| 366 | 365 | ||
| 367 | handle_exception_special: | 366 | handle_exception_special: |
| 367 | setup_frame_reg | ||
| 368 | |||
| 368 | ! Setup return address and jump to exception handler | 369 | ! Setup return address and jump to exception handler |
| 369 | mov.l 7f, r9 ! fetch return address | 370 | mov.l 7f, r9 ! fetch return address |
| 370 | stc r2_bank, r0 ! k2 (vector) | 371 | stc r2_bank, r0 ! k2 (vector) |
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index 3576b709f052..e51168064e56 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c | |||
| @@ -540,6 +540,8 @@ void dwarf_free_frame(struct dwarf_frame *frame) | |||
| 540 | mempool_free(frame, dwarf_frame_pool); | 540 | mempool_free(frame, dwarf_frame_pool); |
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | extern void ret_from_irq(void); | ||
| 544 | |||
| 543 | /** | 545 | /** |
| 544 | * dwarf_unwind_stack - unwind the stack | 546 | * dwarf_unwind_stack - unwind the stack |
| 545 | * | 547 | * |
| @@ -678,6 +680,24 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | |||
| 678 | addr = frame->cfa + reg->addr; | 680 | addr = frame->cfa + reg->addr; |
| 679 | frame->return_addr = __raw_readl(addr); | 681 | frame->return_addr = __raw_readl(addr); |
| 680 | 682 | ||
| 683 | /* | ||
| 684 | * Ah, the joys of unwinding through interrupts. | ||
| 685 | * | ||
| 686 | * Interrupts are tricky - the DWARF info needs to be _really_ | ||
| 687 | * accurate and unfortunately I'm seeing a lot of bogus DWARF | ||
| 688 | * info. For example, I've seen interrupts occur in epilogues | ||
| 689 | * just after the frame pointer (r14) had been restored. The | ||
| 690 | * problem was that the DWARF info claimed that the CFA could be | ||
| 691 | * reached by using the value of the frame pointer before it was | ||
| 692 | * restored. | ||
| 693 | * | ||
| 694 | * So until the compiler can be trusted to produce reliable | ||
| 695 | * DWARF info when it really matters, let's stop unwinding once | ||
| 696 | * we've calculated the function that was interrupted. | ||
| 697 | */ | ||
| 698 | if (prev && prev->pc == (unsigned long)ret_from_irq) | ||
| 699 | frame->return_addr = 0; | ||
| 700 | |||
| 681 | return frame; | 701 | return frame; |
| 682 | 702 | ||
| 683 | bail: | 703 | bail: |
| @@ -892,18 +912,18 @@ static struct unwinder dwarf_unwinder = { | |||
| 892 | 912 | ||
| 893 | static void dwarf_unwinder_cleanup(void) | 913 | static void dwarf_unwinder_cleanup(void) |
| 894 | { | 914 | { |
| 895 | struct dwarf_cie *cie; | 915 | struct dwarf_cie *cie, *cie_tmp; |
| 896 | struct dwarf_fde *fde; | 916 | struct dwarf_fde *fde, *fde_tmp; |
| 897 | 917 | ||
| 898 | /* | 918 | /* |
| 899 | * Deallocate all the memory allocated for the DWARF unwinder. | 919 | * Deallocate all the memory allocated for the DWARF unwinder. |
| 900 | * Traverse all the FDE/CIE lists and remove and free all the | 920 | * Traverse all the FDE/CIE lists and remove and free all the |
| 901 | * memory associated with those data structures. | 921 | * memory associated with those data structures. |
| 902 | */ | 922 | */ |
| 903 | list_for_each_entry(cie, &dwarf_cie_list, link) | 923 | list_for_each_entry_safe(cie, cie_tmp, &dwarf_cie_list, link) |
| 904 | kfree(cie); | 924 | kfree(cie); |
| 905 | 925 | ||
| 906 | list_for_each_entry(fde, &dwarf_fde_list, link) | 926 | list_for_each_entry_safe(fde, fde_tmp, &dwarf_fde_list, link) |
| 907 | kfree(fde); | 927 | kfree(fde); |
| 908 | 928 | ||
| 909 | kmem_cache_destroy(dwarf_reg_cachep); | 929 | kmem_cache_destroy(dwarf_reg_cachep); |
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index f0abd58c3a69..2b15ae60c3a0 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
| @@ -70,8 +70,14 @@ ret_from_exception: | |||
| 70 | CFI_STARTPROC simple | 70 | CFI_STARTPROC simple |
| 71 | CFI_DEF_CFA r14, 0 | 71 | CFI_DEF_CFA r14, 0 |
| 72 | CFI_REL_OFFSET 17, 64 | 72 | CFI_REL_OFFSET 17, 64 |
| 73 | CFI_REL_OFFSET 15, 0 | 73 | CFI_REL_OFFSET 15, 60 |
| 74 | CFI_REL_OFFSET 14, 56 | 74 | CFI_REL_OFFSET 14, 56 |
| 75 | CFI_REL_OFFSET 13, 52 | ||
| 76 | CFI_REL_OFFSET 12, 48 | ||
| 77 | CFI_REL_OFFSET 11, 44 | ||
| 78 | CFI_REL_OFFSET 10, 40 | ||
| 79 | CFI_REL_OFFSET 9, 36 | ||
| 80 | CFI_REL_OFFSET 8, 32 | ||
| 75 | preempt_stop() | 81 | preempt_stop() |
| 76 | ENTRY(ret_from_irq) | 82 | ENTRY(ret_from_irq) |
| 77 | ! | 83 | ! |
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 31f80c61b031..ec79faf6f021 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c | |||
| @@ -368,7 +368,7 @@ void exit_thread(void) | |||
| 368 | void flush_thread(void) | 368 | void flush_thread(void) |
| 369 | { | 369 | { |
| 370 | 370 | ||
| 371 | /* Called by fs/exec.c (flush_old_exec) to remove traces of a | 371 | /* Called by fs/exec.c (setup_new_exec) to remove traces of a |
| 372 | * previously running executable. */ | 372 | * previously running executable. */ |
| 373 | #ifdef CONFIG_SH_FPU | 373 | #ifdef CONFIG_SH_FPU |
| 374 | if (last_task_used_math == current) { | 374 | if (last_task_used_math == current) { |
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 873ebdc4f98e..b063eb8b18e3 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c | |||
| @@ -133,6 +133,8 @@ void user_enable_single_step(struct task_struct *child) | |||
| 133 | struct pt_regs *regs = child->thread.uregs; | 133 | struct pt_regs *regs = child->thread.uregs; |
| 134 | 134 | ||
| 135 | regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ | 135 | regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ |
| 136 | |||
| 137 | set_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
| 136 | } | 138 | } |
| 137 | 139 | ||
| 138 | void user_disable_single_step(struct task_struct *child) | 140 | void user_disable_single_step(struct task_struct *child) |
| @@ -140,6 +142,8 @@ void user_disable_single_step(struct task_struct *child) | |||
| 140 | struct pt_regs *regs = child->thread.uregs; | 142 | struct pt_regs *regs = child->thread.uregs; |
| 141 | 143 | ||
| 142 | regs->sr &= ~SR_SSTEP; | 144 | regs->sr &= ~SR_SSTEP; |
| 145 | |||
| 146 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
| 143 | } | 147 | } |
| 144 | 148 | ||
| 145 | static int genregs_get(struct task_struct *target, | 149 | static int genregs_get(struct task_struct *target, |
| @@ -454,6 +458,8 @@ asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs) | |||
| 454 | 458 | ||
| 455 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) | 459 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) |
| 456 | { | 460 | { |
| 461 | int step; | ||
| 462 | |||
| 457 | if (unlikely(current->audit_context)) | 463 | if (unlikely(current->audit_context)) |
| 458 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), | 464 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), |
| 459 | regs->regs[9]); | 465 | regs->regs[9]); |
| @@ -461,8 +467,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) | |||
| 461 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | 467 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
| 462 | trace_sys_exit(regs, regs->regs[9]); | 468 | trace_sys_exit(regs, regs->regs[9]); |
| 463 | 469 | ||
| 464 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 470 | step = test_thread_flag(TIF_SINGLESTEP); |
| 465 | tracehook_report_syscall_exit(regs, 0); | 471 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) |
| 472 | tracehook_report_syscall_exit(regs, step); | ||
| 466 | } | 473 | } |
| 467 | 474 | ||
| 468 | /* Called with interrupts disabled */ | 475 | /* Called with interrupts disabled */ |
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index ce76dbdef294..580e97d46ca5 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c | |||
| @@ -118,7 +118,9 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
| 118 | * clear the TS_RESTORE_SIGMASK flag. | 118 | * clear the TS_RESTORE_SIGMASK flag. |
| 119 | */ | 119 | */ |
| 120 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 120 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
| 121 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | 121 | |
| 122 | tracehook_signal_handler(signr, &info, &ka, regs, | ||
| 123 | test_thread_flag(TIF_SINGLESTEP)); | ||
| 122 | return 1; | 124 | return 1; |
| 123 | } | 125 | } |
| 124 | } | 126 | } |
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 4bd5a1146956..19fd11dd9871 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S | |||
| @@ -353,4 +353,3 @@ ENTRY(sys_call_table) | |||
| 353 | .long sys_pwritev | 353 | .long sys_pwritev |
| 354 | .long sys_rt_tgsigqueueinfo /* 335 */ | 354 | .long sys_rt_tgsigqueueinfo /* 335 */ |
| 355 | .long sys_perf_event_open | 355 | .long sys_perf_event_open |
| 356 | .long sys_recvmmsg | ||
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 07d2aaea9ae8..2048a20d7c80 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S | |||
| @@ -392,3 +392,4 @@ sys_call_table: | |||
| 392 | .long sys_rt_tgsigqueueinfo | 392 | .long sys_rt_tgsigqueueinfo |
| 393 | .long sys_perf_event_open | 393 | .long sys_perf_event_open |
| 394 | .long sys_recvmmsg /* 365 */ | 394 | .long sys_recvmmsg /* 365 */ |
| 395 | .long sys_accept4 | ||
