Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6.git] / arch / sparc / kernel / helpers.S
1         .align  32
2         .globl  __flushw_user
3         .type   __flushw_user,#function
4 __flushw_user:
5         rdpr    %otherwin, %g1
6         brz,pn  %g1, 2f
7          clr    %g2
8 1:      save    %sp, -128, %sp
9         rdpr    %otherwin, %g1
10         brnz,pt %g1, 1b
11          add    %g2, 1, %g2
12 1:      sub     %g2, 1, %g2
13         brnz,pt %g2, 1b
14          restore %g0, %g0, %g0
15 2:      retl
16          nop
17         .size   __flushw_user,.-__flushw_user
18
19         /* Flush %fp and %i7 to the stack for all register
20          * windows active inside of the cpu.  This allows
21          * show_stack_trace() to avoid using an expensive
22          * 'flushw'.
23          */
24         .globl          stack_trace_flush
25         .type           stack_trace_flush,#function
26 stack_trace_flush:
27         rdpr            %pstate, %o0
28         wrpr            %o0, PSTATE_IE, %pstate
29
30         rdpr            %cwp, %g1
31         rdpr            %canrestore, %g2
32         sub             %g1, 1, %g3
33
34 1:      brz,pn          %g2, 2f
35          sub            %g2, 1, %g2
36         wrpr            %g3, %cwp
37         stx             %fp, [%sp + STACK_BIAS + RW_V9_I6]
38         stx             %i7, [%sp + STACK_BIAS + RW_V9_I7]
39         ba,pt           %xcc, 1b
40          sub            %g3, 1, %g3
41
42 2:      wrpr            %g1, %cwp
43         wrpr            %o0, %pstate
44
45         retl
46          nop
47         .size           stack_trace_flush,.-stack_trace_flush
48
49 #ifdef CONFIG_PERF_EVENTS
50         .globl          perf_arch_fetch_caller_regs
51         .type           perf_arch_fetch_caller_regs,#function
52 perf_arch_fetch_caller_regs:
53         /* We always read the %pstate into %o5 since we will use
54          * that to construct a fake %tstate to store into the regs.
55          */
56         rdpr            %pstate, %o5
57         brz,pn          %o2, 50f
58          mov            %o2, %g7
59
60         /* Turn off interrupts while we walk around the register
61          * window by hand.
62          */
63         wrpr            %o5, PSTATE_IE, %pstate
64
65         /* The %canrestore tells us how many register windows are
66          * still live in the chip above us, past that we have to
67          * walk the frame as saved on the stack.   We stash away
68          * the %cwp in %g1 so we can return back to the original
69          * register window.
70          */
71         rdpr            %cwp, %g1
72         rdpr            %canrestore, %g2
73         sub             %g1, 1, %g3
74
75         /* We have the skip count in %g7, if it hits zero then
76          * %fp/%i7 are the registers we need.  Otherwise if our
77          * %canrestore count maintained in %g2 hits zero we have
78          * to start traversing the stack.
79          */
80 10:     brz,pn          %g2, 4f
81          sub            %g2, 1, %g2
82         wrpr            %g3, %cwp
83         subcc           %g7, 1, %g7
84         bne,pt          %xcc, 10b
85          sub            %g3, 1, %g3
86
87         /* We found the values we need in the cpu's register
88          * windows.
89          */
90         mov             %fp, %g3
91         ba,pt           %xcc, 3f
92          mov            %i7, %g2
93
94 50:     mov             %fp, %g3
95         ba,pt           %xcc, 2f
96          mov            %i7, %g2
97
98         /* We hit the end of the valid register windows in the
99          * cpu, start traversing the stack frame.
100          */
101 4:      mov             %fp, %g3
102
103 20:     ldx             [%g3 + STACK_BIAS + RW_V9_I7], %g2
104         subcc           %g7, 1, %g7
105         bne,pn          %xcc, 20b
106          ldx            [%g3 + STACK_BIAS + RW_V9_I6], %g3
107
108         /* Restore the current register window position and
109          * re-enable interrupts.
110          */
111 3:      wrpr            %g1, %cwp
112         wrpr            %o5, %pstate
113
114 2:      stx             %g3, [%o0 + PT_V9_FP]
115         sllx            %o5, 8, %o5
116         stx             %o5, [%o0 + PT_V9_TSTATE]
117         stx             %g2, [%o0 + PT_V9_TPC]
118         add             %g2, 4, %g2
119         retl
120          stx            %g2, [%o0 + PT_V9_TNPC]
121         .size           perf_arch_fetch_caller_regs,.-perf_arch_fetch_caller_regs
122 #endif /* CONFIG_PERF_EVENTS */
123
124 #ifdef CONFIG_SMP
125         .globl          hard_smp_processor_id
126         .type           hard_smp_processor_id,#function
127 hard_smp_processor_id:
128 #endif
129         .globl          real_hard_smp_processor_id
130         .type           real_hard_smp_processor_id,#function
131 real_hard_smp_processor_id:
132         __GET_CPUID(%o0)
133         retl
134          nop
135 #ifdef CONFIG_SMP
136         .size           hard_smp_processor_id,.-hard_smp_processor_id
137 #endif
138         .size           real_hard_smp_processor_id,.-real_hard_smp_processor_id