diff options
Diffstat (limited to 'arch/sh/kernel/cpu/sh5')
| -rw-r--r-- | arch/sh/kernel/cpu/sh5/clock-sh5.c | 12 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh5/entry.S | 125 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh5/fpu.c | 3 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh5/probe.c | 2 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh5/setup-sh5.c | 91 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh5/unwind.c | 63 |
6 files changed, 93 insertions, 203 deletions
diff --git a/arch/sh/kernel/cpu/sh5/clock-sh5.c b/arch/sh/kernel/cpu/sh5/clock-sh5.c index 9cfc19b8dbe..c48b93d4c08 100644 --- a/arch/sh/kernel/cpu/sh5/clock-sh5.c +++ b/arch/sh/kernel/cpu/sh5/clock-sh5.c @@ -28,7 +28,7 @@ static void master_clk_init(struct clk *clk) clk->rate *= ifc_table[idx]; } -static struct clk_ops sh5_master_clk_ops = { +static struct sh_clk_ops sh5_master_clk_ops = { .init = master_clk_init, }; @@ -38,7 +38,7 @@ static unsigned long module_clk_recalc(struct clk *clk) return clk->parent->rate / ifc_table[idx]; } -static struct clk_ops sh5_module_clk_ops = { +static struct sh_clk_ops sh5_module_clk_ops = { .recalc = module_clk_recalc, }; @@ -48,7 +48,7 @@ static unsigned long bus_clk_recalc(struct clk *clk) return clk->parent->rate / ifc_table[idx]; } -static struct clk_ops sh5_bus_clk_ops = { +static struct sh_clk_ops sh5_bus_clk_ops = { .recalc = bus_clk_recalc, }; @@ -58,18 +58,18 @@ static unsigned long cpu_clk_recalc(struct clk *clk) return clk->parent->rate / ifc_table[idx]; } -static struct clk_ops sh5_cpu_clk_ops = { +static struct sh_clk_ops sh5_cpu_clk_ops = { .recalc = cpu_clk_recalc, }; -static struct clk_ops *sh5_clk_ops[] = { +static struct sh_clk_ops *sh5_clk_ops[] = { &sh5_master_clk_ops, &sh5_module_clk_ops, &sh5_bus_clk_ops, &sh5_cpu_clk_ops, }; -void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx) { cprc_base = (unsigned long)ioremap_nocache(CPRC_BASE, 1024); BUG_ON(!cprc_base); diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index 6b80295dd7a..0c8d0377d40 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -335,7 +335,7 @@ tlb_miss: /* If the fast path handler fixed the fault, just drop through quickly to the restore code right away to return to the excepting context. */ - beqi/u r2, 0, tr1 + bnei/u r2, 0, tr1 fast_tlb_miss_restore: ld.q SP, SAVED_TR0, r2 @@ -933,7 +933,7 @@ ret_with_reschedule: pta restore_all, tr1 - movi _TIF_SIGPENDING, r8 + movi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8 and r8, r7, r8 pta work_notifysig, tr0 bne r8, ZERO, tr0 @@ -1079,9 +1079,8 @@ restore_all: * * Kernel TLB fault handlers will get a slightly different interface. * (r2) struct pt_regs *, original register's frame pointer - * (r3) writeaccess, whether it's a store fault as opposed to load fault - * (r4) execaccess, whether it's a ITLB fault as opposed to DTLB fault - * (r5) Effective Address of fault + * (r3) page fault error code (see asm/thread_info.h) + * (r4) Effective Address of fault * (LINK) return address * (SP) = r2 * @@ -1092,26 +1091,25 @@ restore_all: tlb_miss_load: or SP, ZERO, r2 or ZERO, ZERO, r3 /* Read */ - or ZERO, ZERO, r4 /* Data */ - getcon TEA, r5 + getcon TEA, r4 pta call_do_page_fault, tr0 beq ZERO, ZERO, tr0 tlb_miss_store: or SP, ZERO, r2 - movi 1, r3 /* Write */ - or ZERO, ZERO, r4 /* Data */ - getcon TEA, r5 + movi FAULT_CODE_WRITE, r3 /* Write */ + getcon TEA, r4 pta call_do_page_fault, tr0 beq ZERO, ZERO, tr0 itlb_miss_or_IRQ: pta its_IRQ, tr0 beqi/u r4, EVENT_INTERRUPT, tr0 + + /* ITLB miss */ or SP, ZERO, r2 - or ZERO, ZERO, r3 /* Read */ - movi 1, r4 /* Text */ - getcon TEA, r5 + movi FAULT_CODE_ITLB, r3 + getcon TEA, r4 /* Fall through */ call_do_page_fault: @@ -1230,6 +1228,25 @@ ret_from_fork: pta ret_from_syscall, tr0 blink tr0, ZERO +.global ret_from_kernel_thread +ret_from_kernel_thread: + + movi schedule_tail,r5 + ori r5, 1, r5 + ptabs r5, tr0 + blink tr0, LINK + + ld.q SP, FRAME_R(2), r2 + ld.q SP, FRAME_R(3), r3 + ptabs r3, tr0 + blink tr0, LINK + + ld.q SP, FRAME_S(FSPC), r2 + addi r2, 4, r2 /* Move PC, being pre-execution event */ + st.q SP, FRAME_S(FSPC), r2 + pta ret_from_syscall, tr0 + blink tr0, ZERO + syscall_allowed: /* Use LINK to deflect the exit point, default is syscall_ret */ pta syscall_ret, tr0 @@ -1571,86 +1588,6 @@ ___clear_user_exit: #endif /* CONFIG_MMU */ /* - * int __strncpy_from_user(unsigned long __dest, unsigned long __src, - * int __count) - * - * Inputs: - * (r2) target address - * (r3) source address - * (r4) maximum size in bytes - * - * Ouputs: - * (*r2) copied data - * (r2) -EFAULT (in case of faulting) - * copied data (otherwise) - */ - .global __strncpy_from_user -__strncpy_from_user: - pta ___strncpy_from_user1, tr0 - pta ___strncpy_from_user_done, tr1 - or r4, ZERO, r5 /* r5 = original count */ - beq/u r4, r63, tr1 /* early exit if r4==0 */ - movi -(EFAULT), r6 /* r6 = reply, no real fixup */ - or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ - -___strncpy_from_user1: - ld.b r3, 0, r7 /* Fault address: only in reading */ - st.b r2, 0, r7 - addi r2, 1, r2 - addi r3, 1, r3 - beq/u ZERO, r7, tr1 - addi r4, -1, r4 /* return real number of copied bytes */ - bne/l ZERO, r4, tr0 - -___strncpy_from_user_done: - sub r5, r4, r6 /* If done, return copied */ - -___strncpy_from_user_exit: - or r6, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * extern long __strnlen_user(const char *__s, long __n) - * - * Inputs: - * (r2) source address - * (r3) source size in bytes - * - * Ouputs: - * (r2) -EFAULT (in case of faulting) - * string length (otherwise) - */ - .global __strnlen_user -__strnlen_user: - pta ___strnlen_user_set_reply, tr0 - pta ___strnlen_user1, tr1 - or ZERO, ZERO, r5 /* r5 = counter */ - movi -(EFAULT), r6 /* r6 = reply, no real fixup */ - or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ - beq r3, ZERO, tr0 - -___strnlen_user1: - ldx.b r2, r5, r7 /* Fault address: only in reading */ - addi r3, -1, r3 /* No real fixup */ - addi r5, 1, r5 - beq r3, ZERO, tr0 - bne r7, ZERO, tr1 -! The line below used to be active. This meant led to a junk byte lying between each pair -! of entries in the argv & envp structures in memory. Whilst the program saw the right data -! via the argv and envp arguments to main, it meant the 'flat' representation visible through -! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example. -! addi r5, 1, r5 /* Include '\0' */ - -___strnlen_user_set_reply: - or r5, ZERO, r6 /* If done, return counter */ - -___strnlen_user_exit: - or r6, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* * extern long __get_user_asm_?(void *val, long addr) * * Inputs: @@ -1984,8 +1921,6 @@ asm_uaccess_start: .long ___copy_user2, ___copy_user_exit .long ___clear_user1, ___clear_user_exit #endif - .long ___strncpy_from_user1, ___strncpy_from_user_exit - .long ___strnlen_user1, ___strnlen_user_exit .long ___get_user_asm_b1, ___get_user_asm_b_exit .long ___get_user_asm_w1, ___get_user_asm_w_exit .long ___get_user_asm_l1, ___get_user_asm_l_exit diff --git a/arch/sh/kernel/cpu/sh5/fpu.c b/arch/sh/kernel/cpu/sh5/fpu.c index 4b3bb35e99f..9f8713aa718 100644 --- a/arch/sh/kernel/cpu/sh5/fpu.c +++ b/arch/sh/kernel/cpu/sh5/fpu.c @@ -107,8 +107,5 @@ asmlinkage void do_fpu_error(unsigned long ex, struct pt_regs *regs) regs->pc += 4; - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; - force_sig(SIGFPE, tsk); } diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c index 9e882409e4e..eca427c2f2f 100644 --- a/arch/sh/kernel/cpu/sh5/probe.c +++ b/arch/sh/kernel/cpu/sh5/probe.c @@ -17,7 +17,7 @@ #include <asm/cache.h> #include <asm/tlb.h> -void __cpuinit cpu_probe(void) +void cpu_probe(void) { unsigned long long cir; diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c index 18419f1de96..1bf0b2cf665 100644 --- a/arch/sh/kernel/cpu/sh5/setup-sh5.c +++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c @@ -17,17 +17,23 @@ #include <asm/addrspace.h> static struct plat_sci_port scif0_platform_data = { - .mapbase = PHYS_PERIPHERAL_BLOCK + 0x01030000, .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE, - .scbrr_algo_id = SCBRR_ALGO_2, .type = PORT_SCIF, - .irqs = { 39, 40, 42, 0 }, +}; + +static struct resource scif0_resources[] = { + DEFINE_RES_MEM(PHYS_PERIPHERAL_BLOCK + 0x01030000, 0x100), + DEFINE_RES_IRQ(39), + DEFINE_RES_IRQ(40), + DEFINE_RES_IRQ(42), }; static struct platform_device scif0_device = { .name = "sh-sci", .id = 0, + .resource = scif0_resources, + .num_resources = ARRAY_SIZE(scif0_resources), .dev = { .platform_data = &scif0_platform_data, }, @@ -65,30 +71,20 @@ static struct platform_device rtc_device = { #define TMU_BLOCK_OFF 0x01020000 #define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF -#define TMU0_BASE (TMU_BASE + 0x8 + (0xc * 0x0)) -#define TMU1_BASE (TMU_BASE + 0x8 + (0xc * 0x1)) -#define TMU2_BASE (TMU_BASE + 0x8 + (0xc * 0x2)) static struct sh_timer_config tmu0_platform_data = { - .channel_offset = 0x04, - .timer_bit = 0, - .clockevent_rating = 200, + .channels_mask = 7, }; static struct resource tmu0_resources[] = { - [0] = { - .start = TMU0_BASE, - .end = TMU0_BASE + 0xc - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TUNI0, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_MEM(TMU_BASE, 0x30), + DEFINE_RES_IRQ(IRQ_TUNI0), + DEFINE_RES_IRQ(IRQ_TUNI1), + DEFINE_RES_IRQ(IRQ_TUNI2), }; static struct platform_device tmu0_device = { - .name = "sh_tmu", + .name = "sh-tmu", .id = 0, .dev = { .platform_data = &tmu0_platform_data, @@ -97,66 +93,9 @@ static struct platform_device tmu0_device = { .num_resources = ARRAY_SIZE(tmu0_resources), }; -static struct sh_timer_config tmu1_platform_data = { - .channel_offset = 0x10, - .timer_bit = 1, - .clocksource_rating = 200, -}; - -static struct resource tmu1_resources[] = { - [0] = { - .start = TMU1_BASE, - .end = TMU1_BASE + 0xc - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TUNI1, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device tmu1_device = { - .name = "sh_tmu", - .id = 1, - .dev = { - .platform_data = &tmu1_platform_data, - }, - .resource = tmu1_resources, - .num_resources = ARRAY_SIZE(tmu1_resources), -}; - -static struct sh_timer_config tmu2_platform_data = { - .channel_offset = 0x1c, - .timer_bit = 2, -}; - -static struct resource tmu2_resources[] = { - [0] = { - .start = TMU2_BASE, - .end = TMU2_BASE + 0xc - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TUNI2, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device tmu2_device = { - .name = "sh_tmu", - .id = 2, - .dev = { - .platform_data = &tmu2_platform_data, - }, - .resource = tmu2_resources, - .num_resources = ARRAY_SIZE(tmu2_resources), -}; - static struct platform_device *sh5_early_devices[] __initdata = { &scif0_device, &tmu0_device, - &tmu1_device, - &tmu2_device, }; static struct platform_device *sh5_devices[] __initdata = { diff --git a/arch/sh/kernel/cpu/sh5/unwind.c b/arch/sh/kernel/cpu/sh5/unwind.c index b205b25eaf4..10aed41757f 100644 --- a/arch/sh/kernel/cpu/sh5/unwind.c +++ b/arch/sh/kernel/cpu/sh5/unwind.c @@ -16,6 +16,8 @@ #include <asm/ptrace.h> #include <asm/processor.h> #include <asm/io.h> +#include <asm/unwinder.h> +#include <asm/stacktrace.h> static u8 regcache[63]; @@ -199,8 +201,11 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc, return 0; } -/* Don't put this on the stack since we'll want to call sh64_unwind - * when we're close to underflowing the stack anyway. */ +/* + * Don't put this on the stack since we'll want to call in to + * sh64_unwinder_dump() when we're close to underflowing the stack + * anyway. + */ static struct pt_regs here_regs; extern const char syscall_ret; @@ -208,17 +213,19 @@ extern const char ret_from_syscall; extern const char ret_from_exception; extern const char ret_from_irq; -static void sh64_unwind_inner(struct pt_regs *regs); +static void sh64_unwind_inner(const struct stacktrace_ops *ops, + void *data, struct pt_regs *regs); -static void unwind_nested (unsigned long pc, unsigned long fp) +static inline void unwind_nested(const struct stacktrace_ops *ops, void *data, + unsigned long pc, unsigned long fp) { if ((fp >= __MEMORY_START) && - ((fp & 7) == 0)) { - sh64_unwind_inner((struct pt_regs *) fp); - } + ((fp & 7) == 0)) + sh64_unwind_inner(ops, data, (struct pt_regs *)fp); } -static void sh64_unwind_inner(struct pt_regs *regs) +static void sh64_unwind_inner(const struct stacktrace_ops *ops, + void *data, struct pt_regs *regs) { unsigned long pc, fp; int ofs = 0; @@ -232,29 +239,29 @@ static void sh64_unwind_inner(struct pt_regs *regs) int cond; unsigned long next_fp, next_pc; - if (pc == ((unsigned long) &syscall_ret & ~1)) { + if (pc == ((unsigned long)&syscall_ret & ~1)) { printk("SYSCALL\n"); - unwind_nested(pc,fp); + unwind_nested(ops, data, pc, fp); return; } - if (pc == ((unsigned long) &ret_from_syscall & ~1)) { + if (pc == ((unsigned long)&ret_from_syscall & ~1)) { printk("SYSCALL (PREEMPTED)\n"); - unwind_nested(pc,fp); + unwind_nested(ops, data, pc, fp); return; } /* In this case, the PC is discovered by lookup_prev_stack_frame but it has 4 taken off it to look like the 'caller' */ - if (pc == ((unsigned long) &ret_from_exception & ~1)) { + if (pc == ((unsigned long)&ret_from_exception & ~1)) { printk("EXCEPTION\n"); - unwind_nested(pc,fp); + unwind_nested(ops, data, pc, fp); return; } - if (pc == ((unsigned long) &ret_from_irq & ~1)) { + if (pc == ((unsigned long)&ret_from_irq & ~1)) { printk("IRQ\n"); - unwind_nested(pc,fp); + unwind_nested(ops, data, pc, fp); return; } @@ -263,8 +270,7 @@ static void sh64_unwind_inner(struct pt_regs *regs) pc -= ofs; - printk("[<%08lx>] ", pc); - print_symbol("%s\n", pc); + ops->address(data, pc, 1); if (first_pass) { /* If the innermost frame is a leaf function, it's @@ -287,10 +293,13 @@ static void sh64_unwind_inner(struct pt_regs *regs) } printk("\n"); - } -void sh64_unwind(struct pt_regs *regs) +static void sh64_unwinder_dump(struct task_struct *task, + struct pt_regs *regs, + unsigned long *sp, + const struct stacktrace_ops *ops, + void *data) { if (!regs) { /* @@ -320,7 +329,17 @@ void sh64_unwind(struct pt_regs *regs) ); } - printk("\nCall Trace:\n"); - sh64_unwind_inner(regs); + sh64_unwind_inner(ops, data, regs); } +static struct unwinder sh64_unwinder = { + .name = "sh64-unwinder", + .dump = sh64_unwinder_dump, + .rating = 150, +}; + +static int __init sh64_unwinder_init(void) +{ + return unwinder_register(&sh64_unwinder); +} +early_initcall(sh64_unwinder_init); |
