diff options
Diffstat (limited to 'arch/sh/kernel')
| -rw-r--r-- | arch/sh/kernel/entry-common.S | 2 | ||||
| -rw-r--r-- | arch/sh/kernel/io_generic.c | 3 | ||||
| -rw-r--r-- | arch/sh/kernel/process.c | 5 | ||||
| -rw-r--r-- | arch/sh/kernel/ptrace.c | 45 | ||||
| -rw-r--r-- | arch/sh/kernel/signal.c | 4 | ||||
| -rw-r--r-- | arch/sh/kernel/vmlinux.lds.S | 3 |
6 files changed, 41 insertions, 21 deletions
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index ab4ebb856c2a..b46728027195 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
| @@ -224,7 +224,7 @@ work_resched: | |||
| 224 | syscall_exit_work: | 224 | syscall_exit_work: |
| 225 | ! r0: current_thread_info->flags | 225 | ! r0: current_thread_info->flags |
| 226 | ! r8: current_thread_info | 226 | ! r8: current_thread_info |
| 227 | tst #_TIF_SYSCALL_TRACE, r0 | 227 | tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP, r0 |
| 228 | bt/s work_pending | 228 | bt/s work_pending |
| 229 | tst #_TIF_NEED_RESCHED, r0 | 229 | tst #_TIF_NEED_RESCHED, r0 |
| 230 | #ifdef CONFIG_TRACE_IRQFLAGS | 230 | #ifdef CONFIG_TRACE_IRQFLAGS |
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index 66626c03e1ee..771ea4230441 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <asm/machvec.h> | 16 | #include <asm/machvec.h> |
| 17 | #include <asm/cacheflush.h> | ||
| 18 | 17 | ||
| 19 | #ifdef CONFIG_CPU_SH3 | 18 | #ifdef CONFIG_CPU_SH3 |
| 20 | /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a | 19 | /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a |
| @@ -96,7 +95,6 @@ void generic_insw(unsigned long port, void *dst, unsigned long count) | |||
| 96 | while (count--) | 95 | while (count--) |
| 97 | *buf++ = *port_addr; | 96 | *buf++ = *port_addr; |
| 98 | 97 | ||
| 99 | flush_dcache_all(); | ||
| 100 | dummy_read(); | 98 | dummy_read(); |
| 101 | } | 99 | } |
| 102 | 100 | ||
| @@ -171,7 +169,6 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count) | |||
| 171 | while (count--) | 169 | while (count--) |
| 172 | *port_addr = *buf++; | 170 | *port_addr = *buf++; |
| 173 | 171 | ||
| 174 | flush_dcache_all(); | ||
| 175 | dummy_read(); | 172 | dummy_read(); |
| 176 | } | 173 | } |
| 177 | 174 | ||
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 9d6a438b3eaf..e7607366ac4e 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c | |||
| @@ -250,12 +250,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
| 250 | childregs->regs[15] = usp; | 250 | childregs->regs[15] = usp; |
| 251 | ti->addr_limit = USER_DS; | 251 | ti->addr_limit = USER_DS; |
| 252 | } else { | 252 | } else { |
| 253 | childregs->regs[15] = (unsigned long)task_stack_page(p) + | 253 | childregs->regs[15] = (unsigned long)childregs; |
| 254 | THREAD_SIZE; | ||
| 255 | ti->addr_limit = KERNEL_DS; | 254 | ti->addr_limit = KERNEL_DS; |
| 256 | } | 255 | } |
| 257 | 256 | ||
| 258 | if (clone_flags & CLONE_SETTLS) | 257 | if (clone_flags & CLONE_SETTLS) |
| 259 | childregs->gbr = childregs->regs[0]; | 258 | childregs->gbr = childregs->regs[0]; |
| 260 | 259 | ||
| 261 | childregs->regs[0] = 0; /* Set return value for child */ | 260 | childregs->regs[0] = 0; /* Set return value for child */ |
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 04ca13a041c1..855f7246cfff 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka | 8 | * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka |
| 9 | * | 9 | * |
| 10 | */ | 10 | */ |
| 11 | |||
| 12 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 13 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
| 14 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
| @@ -20,8 +19,7 @@ | |||
| 20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 21 | #include <linux/security.h> | 20 | #include <linux/security.h> |
| 22 | #include <linux/signal.h> | 21 | #include <linux/signal.h> |
| 23 | 22 | #include <linux/io.h> | |
| 24 | #include <asm/io.h> | ||
| 25 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
| 26 | #include <asm/pgtable.h> | 24 | #include <asm/pgtable.h> |
| 27 | #include <asm/system.h> | 25 | #include <asm/system.h> |
| @@ -59,6 +57,23 @@ static inline int put_stack_long(struct task_struct *task, int offset, | |||
| 59 | return 0; | 57 | return 0; |
| 60 | } | 58 | } |
| 61 | 59 | ||
| 60 | static void ptrace_disable_singlestep(struct task_struct *child) | ||
| 61 | { | ||
| 62 | clear_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Ensure the UBC is not programmed at the next context switch. | ||
| 66 | * | ||
| 67 | * Normally this is not needed but there are sequences such as | ||
| 68 | * singlestep, signal delivery, and continue that leave the | ||
| 69 | * ubc_pc non-zero leading to spurious SIGTRAPs. | ||
| 70 | */ | ||
| 71 | if (child->thread.ubc_pc != 0) { | ||
| 72 | ubc_usercnt -= 1; | ||
| 73 | child->thread.ubc_pc = 0; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 62 | /* | 77 | /* |
| 63 | * Called by kernel/ptrace.c when detaching.. | 78 | * Called by kernel/ptrace.c when detaching.. |
| 64 | * | 79 | * |
| @@ -66,7 +81,7 @@ static inline int put_stack_long(struct task_struct *task, int offset, | |||
| 66 | */ | 81 | */ |
| 67 | void ptrace_disable(struct task_struct *child) | 82 | void ptrace_disable(struct task_struct *child) |
| 68 | { | 83 | { |
| 69 | /* nothing to do.. */ | 84 | ptrace_disable_singlestep(child); |
| 70 | } | 85 | } |
| 71 | 86 | ||
| 72 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 87 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
| @@ -76,7 +91,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 76 | 91 | ||
| 77 | switch (request) { | 92 | switch (request) { |
| 78 | /* when I and D space are separate, these will need to be fixed. */ | 93 | /* when I and D space are separate, these will need to be fixed. */ |
| 79 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 94 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| 80 | case PTRACE_PEEKDATA: { | 95 | case PTRACE_PEEKDATA: { |
| 81 | unsigned long tmp; | 96 | unsigned long tmp; |
| 82 | int copied; | 97 | int copied; |
| @@ -94,7 +109,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 94 | unsigned long tmp; | 109 | unsigned long tmp; |
| 95 | 110 | ||
| 96 | ret = -EIO; | 111 | ret = -EIO; |
| 97 | if ((addr & 3) || addr < 0 || | 112 | if ((addr & 3) || addr < 0 || |
| 98 | addr > sizeof(struct user) - 3) | 113 | addr > sizeof(struct user) - 3) |
| 99 | break; | 114 | break; |
| 100 | 115 | ||
| @@ -129,7 +144,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 129 | 144 | ||
| 130 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 145 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
| 131 | ret = -EIO; | 146 | ret = -EIO; |
| 132 | if ((addr & 3) || addr < 0 || | 147 | if ((addr & 3) || addr < 0 || |
| 133 | addr > sizeof(struct user) - 3) | 148 | addr > sizeof(struct user) - 3) |
| 134 | break; | 149 | break; |
| 135 | 150 | ||
| @@ -156,6 +171,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 156 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 171 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| 157 | else | 172 | else |
| 158 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 173 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| 174 | |||
| 175 | ptrace_disable_singlestep(child); | ||
| 176 | |||
| 159 | child->exit_code = data; | 177 | child->exit_code = data; |
| 160 | wake_up_process(child); | 178 | wake_up_process(child); |
| 161 | ret = 0; | 179 | ret = 0; |
| @@ -163,14 +181,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 163 | } | 181 | } |
| 164 | 182 | ||
| 165 | /* | 183 | /* |
| 166 | * make the child exit. Best I can do is send it a sigkill. | 184 | * make the child exit. Best I can do is send it a sigkill. |
| 167 | * perhaps it should be put in the status that it wants to | 185 | * perhaps it should be put in the status that it wants to |
| 168 | * exit. | 186 | * exit. |
| 169 | */ | 187 | */ |
| 170 | case PTRACE_KILL: { | 188 | case PTRACE_KILL: { |
| 171 | ret = 0; | 189 | ret = 0; |
| 172 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | 190 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ |
| 173 | break; | 191 | break; |
| 192 | ptrace_disable_singlestep(child); | ||
| 174 | child->exit_code = SIGKILL; | 193 | child->exit_code = SIGKILL; |
| 175 | wake_up_process(child); | 194 | wake_up_process(child); |
| 176 | break; | 195 | break; |
| @@ -196,6 +215,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 196 | ubc_usercnt += 1; | 215 | ubc_usercnt += 1; |
| 197 | child->thread.ubc_pc = pc; | 216 | child->thread.ubc_pc = pc; |
| 198 | 217 | ||
| 218 | set_tsk_thread_flag(child, TIF_SINGLESTEP); | ||
| 199 | child->exit_code = data; | 219 | child->exit_code = data; |
| 200 | /* give it a chance to run. */ | 220 | /* give it a chance to run. */ |
| 201 | wake_up_process(child); | 221 | wake_up_process(child); |
| @@ -248,14 +268,15 @@ asmlinkage void do_syscall_trace(void) | |||
| 248 | { | 268 | { |
| 249 | struct task_struct *tsk = current; | 269 | struct task_struct *tsk = current; |
| 250 | 270 | ||
| 251 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | 271 | if (!test_thread_flag(TIF_SYSCALL_TRACE) && |
| 272 | !test_thread_flag(TIF_SINGLESTEP)) | ||
| 252 | return; | 273 | return; |
| 253 | if (!(tsk->ptrace & PT_PTRACED)) | 274 | if (!(tsk->ptrace & PT_PTRACED)) |
| 254 | return; | 275 | return; |
| 255 | /* the 0x80 provides a way for the tracing parent to distinguish | 276 | /* the 0x80 provides a way for the tracing parent to distinguish |
| 256 | between a syscall stop and SIGTRAP delivery */ | 277 | between a syscall stop and SIGTRAP delivery */ |
| 257 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) | 278 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && |
| 258 | ? 0x80 : 0)); | 279 | !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); |
| 259 | 280 | ||
| 260 | /* | 281 | /* |
| 261 | * this isn't the same as continuing with a signal, but it will do | 282 | * this isn't the same as continuing with a signal, but it will do |
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 32f10a03fbb5..9f39ef1f73da 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c | |||
| @@ -589,6 +589,8 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) | |||
| 589 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 589 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
| 590 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 590 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
| 591 | } | 591 | } |
| 592 | |||
| 593 | return; | ||
| 592 | } | 594 | } |
| 593 | 595 | ||
| 594 | no_signal: | 596 | no_signal: |
| @@ -598,7 +600,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) | |||
| 598 | if (regs->regs[0] == -ERESTARTNOHAND || | 600 | if (regs->regs[0] == -ERESTARTNOHAND || |
| 599 | regs->regs[0] == -ERESTARTSYS || | 601 | regs->regs[0] == -ERESTARTSYS || |
| 600 | regs->regs[0] == -ERESTARTNOINTR) { | 602 | regs->regs[0] == -ERESTARTNOINTR) { |
| 601 | regs->regs[0] = save_r0; | 603 | regs->regs[0] = save_r0; |
| 602 | regs->pc -= 2; | 604 | regs->pc -= 2; |
| 603 | } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { | 605 | } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { |
| 604 | regs->pc -= 2; | 606 | regs->pc -= 2; |
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 75de165867a0..78a6c09875b2 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * Written by Niibe Yutaka | 3 | * Written by Niibe Yutaka |
| 4 | */ | 4 | */ |
| 5 | #include <asm/thread_info.h> | 5 | #include <asm/thread_info.h> |
| 6 | #include <asm/cache.h> | ||
| 6 | #include <asm-generic/vmlinux.lds.h> | 7 | #include <asm-generic/vmlinux.lds.h> |
| 7 | 8 | ||
| 8 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | 9 | #ifdef CONFIG_CPU_LITTLE_ENDIAN |
| @@ -53,7 +54,7 @@ SECTIONS | |||
| 53 | . = ALIGN(PAGE_SIZE); | 54 | . = ALIGN(PAGE_SIZE); |
| 54 | .data.page_aligned : { *(.data.page_aligned) } | 55 | .data.page_aligned : { *(.data.page_aligned) } |
| 55 | 56 | ||
| 56 | . = ALIGN(32); | 57 | . = ALIGN(L1_CACHE_BYTES); |
| 57 | __per_cpu_start = .; | 58 | __per_cpu_start = .; |
| 58 | .data.percpu : { *(.data.percpu) } | 59 | .data.percpu : { *(.data.percpu) } |
| 59 | __per_cpu_end = .; | 60 | __per_cpu_end = .; |
