summaryrefslogtreecommitdiff
path: root/arch/sh/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/cpu/init.c20
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S1
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S5
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c13
-rw-r--r--arch/sh/kernel/entry-common.S2
-rw-r--r--arch/sh/kernel/io_generic.c3
-rw-r--r--arch/sh/kernel/irq.c15
-rw-r--r--arch/sh/kernel/process.c5
-rw-r--r--arch/sh/kernel/ptrace.c45
-rw-r--r--arch/sh/kernel/sh_ksyms.c3
-rw-r--r--arch/sh/kernel/signal.c4
-rw-r--r--arch/sh/kernel/vmlinux.lds.S3
12 files changed, 65 insertions, 54 deletions
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 4b339a640b13..726acfcb9b77 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -3,7 +3,7 @@
*
* CPU init code
*
- * Copyright (C) 2002 - 2006 Paul Mundt
+ * Copyright (C) 2002 - 2007 Paul Mundt
* Copyright (C) 2003 Richard Curnow
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -48,8 +48,19 @@ static void __init cache_init(void)
{
unsigned long ccr, flags;
- if (current_cpu_data.type == CPU_SH_NONE)
- panic("Unknown CPU");
+ /* First setup the rest of the I-cache info */
+ current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr -
+ current_cpu_data.icache.linesz;
+
+ current_cpu_data.icache.way_size = current_cpu_data.icache.sets *
+ current_cpu_data.icache.linesz;
+
+ /* And the D-cache too */
+ current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr -
+ current_cpu_data.dcache.linesz;
+
+ current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
+ current_cpu_data.dcache.linesz;
jump_to_P2();
ccr = ctrl_inl(CCR);
@@ -200,6 +211,9 @@ asmlinkage void __init sh_cpu_init(void)
/* First, probe the CPU */
detect_cpu_and_cache_system();
+ if (current_cpu_data.type == CPU_SH_NONE)
+ panic("Unknown CPU");
+
/* Init the cache */
cache_init();
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index 7f7d292f36ec..c16dc8fec489 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -165,6 +165,7 @@ ENTRY(exception_handler)
interrupt_entry:
mov r9,r4
+ mov r15,r5
mov.l 6f,r9
mov.l 7f,r8
jmp @r8
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index c19205b0f2c0..f3e827f29a46 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -514,13 +514,16 @@ skip_save:
interrupt_exception:
mov.l 1f, r9
+ mov.l 2f, r4
+ mov.l @r4, r4
jmp @r9
- nop
+ mov r15, r5
rts
nop
.align 2
1: .long do_IRQ
+2: .long INTEVT
.align 2
ENTRY(exception_none)
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 9d28c88d2f9d..58950de2696d 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -195,13 +195,6 @@ int __init detect_cpu_and_cache_system(void)
}
- /* Setup the rest of the I-cache info */
- current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr -
- current_cpu_data.icache.linesz;
-
- current_cpu_data.icache.way_size = current_cpu_data.icache.sets *
- current_cpu_data.icache.linesz;
-
/* And the rest of the D-cache */
if (current_cpu_data.dcache.ways > 1) {
size = sizes[(cvr >> 16) & 0xf];
@@ -209,12 +202,6 @@ int __init detect_cpu_and_cache_system(void)
current_cpu_data.dcache.sets = (size >> 6);
}
- current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr -
- current_cpu_data.dcache.linesz;
-
- current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets *
- current_cpu_data.dcache.linesz;
-
/*
* Setup the L2 cache desc
*
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:
syscall_exit_work:
! r0: current_thread_info->flags
! r8: current_thread_info
- tst #_TIF_SYSCALL_TRACE, r0
+ tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP, r0
bt/s work_pending
tst #_TIF_NEED_RESCHED, r0
#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 @@
#include <linux/module.h>
#include <linux/io.h>
#include <asm/machvec.h>
-#include <asm/cacheflush.h>
#ifdef CONFIG_CPU_SH3
/* 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)
while (count--)
*buf++ = *port_addr;
- flush_dcache_all();
dummy_read();
}
@@ -171,7 +169,6 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count)
while (count--)
*port_addr = *buf++;
- flush_dcache_all();
dummy_read();
}
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 67be2b6e8cd1..9bdd8a00cd4a 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
-#include <linux/io.h>
#include <linux/irq.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
@@ -82,13 +81,9 @@ static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
#endif
-asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7,
- struct pt_regs __regs)
+asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
{
- struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
struct pt_regs *old_regs = set_irq_regs(regs);
- int irq;
#ifdef CONFIG_4KSTACKS
union irq_ctx *curctx, *irqctx;
#endif
@@ -111,13 +106,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
}
#endif
-#ifdef CONFIG_CPU_HAS_INTEVT
- irq = evt2irq(ctrl_inl(INTEVT));
-#else
- irq = r4;
-#endif
-
- irq = irq_demux(irq);
+ irq = irq_demux(evt2irq(irq));
#ifdef CONFIG_4KSTACKS
curctx = (union irq_ctx *)current_thread_info();
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,
childregs->regs[15] = usp;
ti->addr_limit = USER_DS;
} else {
- childregs->regs[15] = (unsigned long)task_stack_page(p) +
- THREAD_SIZE;
+ childregs->regs[15] = (unsigned long)childregs;
ti->addr_limit = KERNEL_DS;
}
- if (clone_flags & CLONE_SETTLS)
+ if (clone_flags & CLONE_SETTLS)
childregs->gbr = childregs->regs[0];
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 @@
* SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
*
*/
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -20,8 +19,7 @@
#include <linux/slab.h>
#include <linux/security.h>
#include <linux/signal.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -59,6 +57,23 @@ static inline int put_stack_long(struct task_struct *task, int offset,
return 0;
}
+static void ptrace_disable_singlestep(struct task_struct *child)
+{
+ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+
+ /*
+ * Ensure the UBC is not programmed at the next context switch.
+ *
+ * Normally this is not needed but there are sequences such as
+ * singlestep, signal delivery, and continue that leave the
+ * ubc_pc non-zero leading to spurious SIGTRAPs.
+ */
+ if (child->thread.ubc_pc != 0) {
+ ubc_usercnt -= 1;
+ child->thread.ubc_pc = 0;
+ }
+}
+
/*
* Called by kernel/ptrace.c when detaching..
*
@@ -66,7 +81,7 @@ static inline int put_stack_long(struct task_struct *task, int offset,
*/
void ptrace_disable(struct task_struct *child)
{
- /* nothing to do.. */
+ ptrace_disable_singlestep(child);
}
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)
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
int copied;
@@ -94,7 +109,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp;
ret = -EIO;
- if ((addr & 3) || addr < 0 ||
+ if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3)
break;
@@ -129,7 +144,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO;
- if ((addr & 3) || addr < 0 ||
+ if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3)
break;
@@ -156,6 +171,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+ ptrace_disable_singlestep(child);
+
child->exit_code = data;
wake_up_process(child);
ret = 0;
@@ -163,14 +181,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
/*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
* exit.
*/
case PTRACE_KILL: {
ret = 0;
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
break;
+ ptrace_disable_singlestep(child);
child->exit_code = SIGKILL;
wake_up_process(child);
break;
@@ -196,6 +215,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ubc_usercnt += 1;
child->thread.ubc_pc = pc;
+ set_tsk_thread_flag(child, TIF_SINGLESTEP);
child->exit_code = data;
/* give it a chance to run. */
wake_up_process(child);
@@ -248,14 +268,15 @@ asmlinkage void do_syscall_trace(void)
{
struct task_struct *tsk = current;
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
+ !test_thread_flag(TIF_SINGLESTEP))
return;
if (!(tsk->ptrace & PT_PTRACED))
return;
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0));
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
+ !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index fe1b276c97c6..6e0d10fac4a8 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -82,9 +82,6 @@ DECLARE_EXPORT(__movstr);
DECLARE_EXPORT(__movmem_i4_even);
DECLARE_EXPORT(__movmem_i4_odd);
DECLARE_EXPORT(__movmemSI12_i4);
-DECLARE_EXPORT(__sdivsi3_i4i);
-DECLARE_EXPORT(__udiv_qrnnd_16);
-DECLARE_EXPORT(__udivsi3_i4i);
#else /* GCC 3.x */
DECLARE_EXPORT(__movstr_i4_even);
DECLARE_EXPORT(__movstr_i4_odd);
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)
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
+
+ return;
}
no_signal:
@@ -598,7 +600,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
if (regs->regs[0] == -ERESTARTNOHAND ||
regs->regs[0] == -ERESTARTSYS ||
regs->regs[0] == -ERESTARTNOINTR) {
- regs->regs[0] = save_r0;
+ regs->regs[0] = save_r0;
regs->pc -= 2;
} else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
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 @@
* Written by Niibe Yutaka
*/
#include <asm/thread_info.h>
+#include <asm/cache.h>
#include <asm-generic/vmlinux.lds.h>
#ifdef CONFIG_CPU_LITTLE_ENDIAN
@@ -53,7 +54,7 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
.data.page_aligned : { *(.data.page_aligned) }
- . = ALIGN(32);
+ . = ALIGN(L1_CACHE_BYTES);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;