From 87e8f0e3e6d0b720a2462ebc5667eaa462752f74 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Apr 2010 02:31:50 -0700 Subject: [PATCH 1/4] 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(+) 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]; From 667f0cee3e0321151aa7a1a5222afe67ca4be0ea Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Apr 2010 03:08:11 -0700 Subject: [PATCH 2/4] 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(-) 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); } From be94bbb5db4de0f3a2a5405511ea3ebea261f2c8 Mon Sep 17 00:00:00 2001 From: Jan Blunck Date: Tue, 27 Apr 2010 18:48:52 -0700 Subject: [PATCH 3/4] drivers/sbus/char/flash.c: flash_read should update ppos instead of file->f_pos flash_read() updates file->f_pos directly instead of the ppos given. The VFS later updates the file->f_pos and overwrites it with the unchanged value of ppos. Signed-off-by: Jan Blunck Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/sbus/char/flash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 19f255b97c86..d3b62eb0fba7 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -105,9 +105,9 @@ static ssize_t flash_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - unsigned long p = file->f_pos; + loff_t p = *ppos; int i; - + if (count > flash.read_size - p) count = flash.read_size - p; @@ -118,7 +118,7 @@ flash_read(struct file * file, char __user * buf, buf++; } - file->f_pos += count; + *ppos += count; return count; } From 273fca0ecad9305247043815e185d1bfd04047d4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 18 May 2010 15:23:58 -0700 Subject: [PATCH 4/4] sparc: Define ARCH_SLAB_MINALIGN Because SLOB fancies being different, the default minimum alignment is only "unsigned long" instead of SLAB/SLUB where the default is "unsigned long long" The inconsistency makes no sense and is asking for trouble, but define ARCH_SLAB_MINALIGN to get it right in all cases even after they fix the inconsistency. Signed-off-by: David S. Miller --- arch/sparc/include/asm/cache.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sparc/include/asm/cache.h b/arch/sparc/include/asm/cache.h index 41f85ae4bd4a..78b07009f60a 100644 --- a/arch/sparc/include/asm/cache.h +++ b/arch/sparc/include/asm/cache.h @@ -7,6 +7,8 @@ #ifndef _SPARC_CACHE_H #define _SPARC_CACHE_H +#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long) + #define L1_CACHE_SHIFT 5 #define L1_CACHE_BYTES 32 #define L1_CACHE_ALIGN(x) ((((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)))