From 89c3de079d3123306e33b382296aaa908ce44f0f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 3 Apr 2010 23:50:59 -0700 Subject: [PATCH] --- yaml --- r: 189442 b: refs/heads/master c: 954fbc8985328a3b59b5881243d3aa04a8f8da7c h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/sparc/kernel/helpers.S | 75 +++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index f3cdf137f43f..df8eae4c8123 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3f6c148df42d98f0991baf4353497d380a30bc19 +refs/heads/master: 954fbc8985328a3b59b5881243d3aa04a8f8da7c diff --git a/trunk/arch/sparc/kernel/helpers.S b/trunk/arch/sparc/kernel/helpers.S index 314dd0c9fc5b..92090cc9e829 100644 --- a/trunk/arch/sparc/kernel/helpers.S +++ b/trunk/arch/sparc/kernel/helpers.S @@ -46,6 +46,81 @@ stack_trace_flush: nop .size stack_trace_flush,.-stack_trace_flush +#ifdef CONFIG_PERF_EVENTS + .globl perf_arch_fetch_caller_regs + .type perf_arch_fetch_caller_regs,#function +perf_arch_fetch_caller_regs: + /* We always read the %pstate into %o5 since we will use + * that to construct a fake %tstate to store into the regs. + */ + rdpr %pstate, %o5 + brz,pn %o2, 50f + mov %o2, %g7 + + /* Turn off interrupts while we walk around the register + * window by hand. + */ + wrpr %o5, PSTATE_IE, %pstate + + /* The %canrestore tells us how many register windows are + * still live in the chip above us, past that we have to + * walk the frame as saved on the stack. We stash away + * the %cwp in %g1 so we can return back to the original + * register window. + */ + rdpr %cwp, %g1 + rdpr %canrestore, %g2 + sub %g1, 1, %g3 + + /* We have the skip count in %g7, if it hits zero then + * %fp/%i7 are the registers we need. Otherwise if our + * %canrestore count maintained in %g2 hits zero we have + * to start traversing the stack. + */ +10: brz,pn %g2, 4f + sub %g2, 1, %g2 + wrpr %g3, %cwp + subcc %g7, 1, %g7 + bne,pt %xcc, 10b + sub %g3, 1, %g3 + + /* We found the values we need in the cpu's register + * windows. + */ + mov %fp, %g3 + ba,pt %xcc, 3f + mov %i7, %g2 + +50: mov %fp, %g3 + ba,pt %xcc, 2f + mov %i7, %g2 + + /* We hit the end of the valid register windows in the + * cpu, start traversing the stack frame. + */ +4: mov %fp, %g3 + +20: ldx [%g3 + STACK_BIAS + RW_V9_I7], %g2 + subcc %g7, 1, %g7 + bne,pn %xcc, 20b + ldx [%g3 + STACK_BIAS + RW_V9_I6], %g3 + + /* Restore the current register window position and + * re-enable interrupts. + */ +3: wrpr %g1, %cwp + wrpr %o5, %pstate + +2: stx %g3, [%o0 + PT_V9_FP] + sllx %o5, 8, %o5 + stx %o5, [%o0 + PT_V9_TSTATE] + stx %g2, [%o0 + PT_V9_TPC] + add %g2, 4, %g2 + retl + stx %g2, [%o0 + PT_V9_TNPC] + .size perf_arch_fetch_caller_regs,.-perf_arch_fetch_caller_regs +#endif /* CONFIG_PERF_EVENTS */ + #ifdef CONFIG_SMP .globl hard_smp_processor_id .type hard_smp_processor_id,#function