From f5c9c9be267f73eda6a668ac81ddde56ed7fa793 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 3 Mar 2010 19:57:27 -0800 Subject: sparc: Convert sparc to use read/update_persistent_clock This patch converts the sparc architecture to use the generic read_persistent_clock and update_persistent_clock interfaces, reducing the amount of arch specific code we have to maintain, and allowing for further cleanups in the future. [ davem: compile fix: Here's a version that compiles, you have to get rid of the now unused variably last_rtc_update since we build with -Werror ] Signed-off-by: John Stultz Acked-by: David S. Miller Cc: Andrew Morton Cc: sparclinux@vger.kernel.org Signed-off-by: Thomas Gleixner --- arch/sparc/kernel/time_32.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c index 0d4c09b15efc..4453003032b5 100644 --- a/arch/sparc/kernel/time_32.c +++ b/arch/sparc/kernel/time_32.c @@ -78,6 +78,11 @@ __volatile__ unsigned int *master_l10_counter; u32 (*do_arch_gettimeoffset)(void); +int update_persistent_clock(struct timespec now) +{ + return set_rtc_mmss(now.tv_sec); +} + /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick @@ -87,9 +92,6 @@ u32 (*do_arch_gettimeoffset)(void); static irqreturn_t timer_interrupt(int dummy, void *dev_id) { - /* last time the cmos clock got updated */ - static long last_rtc_update; - #ifndef CONFIG_SMP profile_tick(CPU_PROFILING); #endif @@ -101,16 +103,6 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id) do_timer(1); - /* Determine when to update the Mostek clock. */ - if (ntp_synced() && - xtime.tv_sec > last_rtc_update + 660 && - (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && - (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ - } write_sequnlock(&xtime_lock); #ifndef CONFIG_SMP -- cgit v1.2.3 From 2e2dc1d755cc5609d0c46d47f7d171318b3bffcd Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 13 Apr 2010 14:28:24 -0700 Subject: sparc: Fix forgotten kmemleak headers inclusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix forgotten kmemleak headers inclusion for kmemleak_not_leak() declaration. This fixes the following build error: arch/sparc/kernel/irq_64.c: In function ‘sun4v_build_virq’: arch/sparc/kernel/irq_64.c:657: error: implicit declaration of function ‘kmemleak_not_leak’ Signed-off-by: Frederic Weisbecker Signed-off-by: David S. Miller --- arch/sparc/kernel/irq_64.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 454ce3a25273..2b04c722cc3e 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From ec687886de00e1e63f3d821ccade9a61590408ed Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 14 Apr 2010 02:04:29 -0700 Subject: sparc64: Run NMIs on the hardirq stack. Otherwise we can overflow the main stack with the function tracer enabled. Signed-off-by: David S. Miller --- arch/sparc/kernel/irq_64.c | 19 +------------------ arch/sparc/kernel/kstack.h | 19 +++++++++++++++++++ arch/sparc/kernel/nmi.c | 7 +++++++ 3 files changed, 27 insertions(+), 18 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 2b04c722cc3e..830d70a3e20b 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -47,6 +47,7 @@ #include "entry.h" #include "cpumap.h" +#include "kstack.h" #define NUM_IVECS (IMAP_INR + 1) @@ -713,24 +714,6 @@ void ack_bad_irq(unsigned int virt_irq) void *hardirq_stack[NR_CPUS]; void *softirq_stack[NR_CPUS]; -static __attribute__((always_inline)) void *set_hardirq_stack(void) -{ - void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; - - __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); - if (orig_sp < sp || - orig_sp > (sp + THREAD_SIZE)) { - sp += THREAD_SIZE - 192 - STACK_BIAS; - __asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); - } - - return orig_sp; -} -static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) -{ - __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); -} - void __irq_entry handler_irq(int irq, struct pt_regs *regs) { unsigned long pstate, bucket_pa; diff --git a/arch/sparc/kernel/kstack.h b/arch/sparc/kernel/kstack.h index 5247283d1c03..53dfb92e09fb 100644 --- a/arch/sparc/kernel/kstack.h +++ b/arch/sparc/kernel/kstack.h @@ -61,4 +61,23 @@ check_magic: } +static inline __attribute__((always_inline)) void *set_hardirq_stack(void) +{ + void *orig_sp, *sp = hardirq_stack[smp_processor_id()]; + + __asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp)); + if (orig_sp < sp || + orig_sp > (sp + THREAD_SIZE)) { + sp += THREAD_SIZE - 192 - STACK_BIAS; + __asm__ __volatile__("mov %0, %%sp" : : "r" (sp)); + } + + return orig_sp; +} + +static inline __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp) +{ + __asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp)); +} + #endif /* _KSTACK_H */ diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index 75a3d1a25356..a4bd7ba74c89 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c @@ -23,6 +23,8 @@ #include #include +#include "kstack.h" + /* We don't have a real NMI on sparc64, but we can fake one * up using profiling counter overflow interrupts and interrupt * levels. @@ -92,6 +94,7 @@ static void die_nmi(const char *str, struct pt_regs *regs, int do_panic) notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) { unsigned int sum, touched = 0; + void *orig_sp; clear_softint(1 << irq); @@ -99,6 +102,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) nmi_enter(); + orig_sp = set_hardirq_stack(); + if (notify_die(DIE_NMI, "nmi", regs, 0, pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) touched = 1; @@ -124,6 +129,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) pcr_ops->write(pcr_enable); } + restore_hardirq_stack(orig_sp); + nmi_exit(); } -- cgit v1.2.3 From baa06775e224e9f74e5c2de894c95cd49678beff Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 19 Apr 2010 13:46:48 -0700 Subject: sparc64: Use correct pt_regs in decode_access_size() error paths. Signed-off-by: David S. Miller --- arch/sparc/kernel/unaligned_64.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index ebce43018c49..c752c4c479bd 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c @@ -50,7 +50,7 @@ static inline enum direction decode_direction(unsigned int insn) } /* 16 = double-word, 8 = extra-word, 4 = word, 2 = half-word */ -static inline int decode_access_size(unsigned int insn) +static inline int decode_access_size(struct pt_regs *regs, unsigned int insn) { unsigned int tmp; @@ -66,7 +66,7 @@ static inline int decode_access_size(unsigned int insn) return 2; else { printk("Impossible unaligned trap. insn=%08x\n", insn); - die_if_kernel("Byte sized unaligned access?!?!", current_thread_info()->kregs); + die_if_kernel("Byte sized unaligned access?!?!", regs); /* GCC should never warn that control reaches the end * of this function without returning a value because @@ -286,7 +286,7 @@ static void log_unaligned(struct pt_regs *regs) asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn) { enum direction dir = decode_direction(insn); - int size = decode_access_size(insn); + int size = decode_access_size(regs, insn); int orig_asi, asi; current_thread_info()->kern_una_regs = regs; -- cgit v1.2.3 From 28a1f533ae8606020238b840b82ae70a3f87609e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 20 Apr 2010 00:48:37 -0700 Subject: sparc64: Fix hardirq tracing in trap return path. We can overflow the hardirq stack if we set the %pil here so early, just let the normal control flow do it. This is fine as we are allowed to do the actual IRQ enable at any point after we call trace_hardirqs_on. Signed-off-by: David S. Miller --- arch/sparc/kernel/rtrap_64.S | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S index 83f1873c6c13..090b9e9ad5e3 100644 --- a/arch/sparc/kernel/rtrap_64.S +++ b/arch/sparc/kernel/rtrap_64.S @@ -130,7 +130,17 @@ rtrap_xcall: nop call trace_hardirqs_on nop - wrpr %l4, %pil + /* Do not actually set the %pil here. We will do that + * below after we clear PSTATE_IE in the %pstate register. + * If we re-enable interrupts here, we can recurse down + * the hardirq stack potentially endlessly, causing a + * stack overflow. + * + * It is tempting to put this test and trace_hardirqs_on + * call at the 'rt_continue' label, but that will not work + * as that path hits unconditionally and we do not want to + * execute this in NMI return paths, for example. + */ #endif rtrap_no_irq_enable: andcc %l1, TSTATE_PRIV, %l3 -- cgit v1.2.3 From 87e8f0e3e6d0b720a2462ebc5667eaa462752f74 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Apr 2010 02:31:50 -0700 Subject: sparc64: Show stack backtrace from show_regs() just like other platforms. Signed-off-by: David S. Miller --- arch/sparc/kernel/process_64.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index a5cf3864b31f..dbe81a368b45 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -202,6 +202,7 @@ void show_regs(struct pt_regs *regs) regs->u_regs[15]); printk("RPC: <%pS>\n", (void *) regs->u_regs[15]); show_regwindow(regs); + show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]); } struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; -- cgit v1.2.3 From 667f0cee3e0321151aa7a1a5222afe67ca4be0ea Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Apr 2010 03:08:11 -0700 Subject: sparc64: Fix stack dumping and tracing when function graph is enabled. Like x86, when the function graph tracer is enabled, emit the ftrace stub as well as the program counter it will be transformed back into. We duplicate a lot of similar stack walking logic in 3 or 4 spots, so eventually we should consolidate things like x86 does. Thanks to Frederic Weisbecker for pointing this out. Signed-off-by: David S. Miller --- arch/sparc/kernel/perf_event.c | 14 ++++++++++++++ arch/sparc/kernel/stacktrace.c | 23 ++++++++++++++++++++++- arch/sparc/kernel/traps_64.c | 14 ++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index e2771939341d..34ce49f80eac 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -1276,6 +1277,9 @@ static void perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry) { unsigned long ksp, fp; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + int graph = 0; +#endif callchain_store(entry, PERF_CONTEXT_KERNEL); callchain_store(entry, regs->tpc); @@ -1303,6 +1307,16 @@ static void perf_callchain_kernel(struct pt_regs *regs, fp = (unsigned long)sf->fp + STACK_BIAS; } callchain_store(entry, pc); +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + if ((pc + 8UL) == (unsigned long) &return_to_handler) { + int index = current->curr_ret_stack; + if (current->ret_stack && index >= graph) { + pc = current->ret_stack[index - graph].ret; + callchain_store(entry, pc); + graph++; + } + } +#endif } while (entry->nr < PERF_MAX_STACK_DEPTH); } diff --git a/arch/sparc/kernel/stacktrace.c b/arch/sparc/kernel/stacktrace.c index acb12f673757..3e0815349630 100644 --- a/arch/sparc/kernel/stacktrace.c +++ b/arch/sparc/kernel/stacktrace.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -12,6 +13,10 @@ static void __save_stack_trace(struct thread_info *tp, bool skip_sched) { unsigned long ksp, fp; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + struct task_struct *t; + int graph = 0; +#endif if (tp == current_thread_info()) { stack_trace_flush(); @@ -21,6 +26,9 @@ static void __save_stack_trace(struct thread_info *tp, } fp = ksp + STACK_BIAS; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + t = tp->task; +#endif do { struct sparc_stackf *sf; struct pt_regs *regs; @@ -44,8 +52,21 @@ static void __save_stack_trace(struct thread_info *tp, if (trace->skip > 0) trace->skip--; - else if (!skip_sched || !in_sched_functions(pc)) + else if (!skip_sched || !in_sched_functions(pc)) { trace->entries[trace->nr_entries++] = pc; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + if ((pc + 8UL) == (unsigned long) &return_to_handler) { + int index = t->curr_ret_stack; + if (t->ret_stack && index >= graph) { + pc = t->ret_stack[index - graph].ret; + if (trace->nr_entries < + trace->max_entries) + trace->entries[trace->nr_entries++] = pc; + graph++; + } + } +#endif + } } while (trace->nr_entries < trace->max_entries); } diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index 9da57f032983..42ad2ba85010 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -2154,6 +2155,9 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) unsigned long fp, thread_base, ksp; struct thread_info *tp; int count = 0; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + int graph = 0; +#endif ksp = (unsigned long) _ksp; if (!tsk) @@ -2193,6 +2197,16 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) } printk(" [%016lx] %pS\n", pc, (void *) pc); +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + if ((pc + 8UL) == (unsigned long) &return_to_handler) { + int index = tsk->curr_ret_stack; + if (tsk->ret_stack && index >= graph) { + pc = tsk->ret_stack[index - graph].ret; + printk(" [%016lx] %pS\n", pc, (void *) pc); + graph++; + } + } +#endif } while (++count < 16); } -- cgit v1.2.3 From c75fbb05b523571c0fdc48d4b968b73f0e20acbb Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Thu, 20 May 2010 21:04:19 -0500 Subject: kgdb,sparc: Add in kgdb_arch_set_pc for sparc The new debug core api requires all architectures that use to debug core to implement a function to set the program counter. Signed-off-by: Jason Wessel Acked-by: David S. Miller --- arch/sparc/kernel/kgdb_32.c | 6 ++++++ arch/sparc/kernel/kgdb_64.c | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'arch/sparc/kernel') diff --git a/arch/sparc/kernel/kgdb_32.c b/arch/sparc/kernel/kgdb_32.c index 04df4edc0073..539243b236fa 100644 --- a/arch/sparc/kernel/kgdb_32.c +++ b/arch/sparc/kernel/kgdb_32.c @@ -158,6 +158,12 @@ void kgdb_arch_exit(void) { } +void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) +{ + regs->pc = ip; + regs->npc = regs->pc + 4; +} + struct kgdb_arch arch_kgdb_ops = { /* Breakpoint instruction: ta 0x7d */ .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d }, diff --git a/arch/sparc/kernel/kgdb_64.c b/arch/sparc/kernel/kgdb_64.c index 0a2bd0f99fc1..768290a6c028 100644 --- a/arch/sparc/kernel/kgdb_64.c +++ b/arch/sparc/kernel/kgdb_64.c @@ -181,6 +181,12 @@ void kgdb_arch_exit(void) { } +void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip) +{ + regs->tpc = ip; + regs->tnpc = regs->tpc + 4; +} + struct kgdb_arch arch_kgdb_ops = { /* Breakpoint instruction: ta 0x72 */ .gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 }, -- cgit v1.2.3