b0f82b81fe
Drop this argument now that we always want to rewind only to the state of the first caller. It means frame pointers are not necessary anymore to reliably get the source of an event. But this also means we need this helper to be a macro now, as an inline function is not an option since we need to know when to provide a default implentation. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Paul Mackerras <paulus@samba.org> Cc: David Miller <davem@davemloft.net> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
139 lines
3.2 KiB
ArmAsm
139 lines
3.2 KiB
ArmAsm
.align 32
|
|
.globl __flushw_user
|
|
.type __flushw_user,#function
|
|
__flushw_user:
|
|
rdpr %otherwin, %g1
|
|
brz,pn %g1, 2f
|
|
clr %g2
|
|
1: save %sp, -128, %sp
|
|
rdpr %otherwin, %g1
|
|
brnz,pt %g1, 1b
|
|
add %g2, 1, %g2
|
|
1: sub %g2, 1, %g2
|
|
brnz,pt %g2, 1b
|
|
restore %g0, %g0, %g0
|
|
2: retl
|
|
nop
|
|
.size __flushw_user,.-__flushw_user
|
|
|
|
/* Flush %fp and %i7 to the stack for all register
|
|
* windows active inside of the cpu. This allows
|
|
* show_stack_trace() to avoid using an expensive
|
|
* 'flushw'.
|
|
*/
|
|
.globl stack_trace_flush
|
|
.type stack_trace_flush,#function
|
|
stack_trace_flush:
|
|
rdpr %pstate, %o0
|
|
wrpr %o0, PSTATE_IE, %pstate
|
|
|
|
rdpr %cwp, %g1
|
|
rdpr %canrestore, %g2
|
|
sub %g1, 1, %g3
|
|
|
|
1: brz,pn %g2, 2f
|
|
sub %g2, 1, %g2
|
|
wrpr %g3, %cwp
|
|
stx %fp, [%sp + STACK_BIAS + RW_V9_I6]
|
|
stx %i7, [%sp + STACK_BIAS + RW_V9_I7]
|
|
ba,pt %xcc, 1b
|
|
sub %g3, 1, %g3
|
|
|
|
2: wrpr %g1, %cwp
|
|
wrpr %o0, %pstate
|
|
|
|
retl
|
|
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
|
|
hard_smp_processor_id:
|
|
#endif
|
|
.globl real_hard_smp_processor_id
|
|
.type real_hard_smp_processor_id,#function
|
|
real_hard_smp_processor_id:
|
|
__GET_CPUID(%o0)
|
|
retl
|
|
nop
|
|
#ifdef CONFIG_SMP
|
|
.size hard_smp_processor_id,.-hard_smp_processor_id
|
|
#endif
|
|
.size real_hard_smp_processor_id,.-real_hard_smp_processor_id
|