Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
[linux-2.6] / arch / sh64 / kernel / switchto.S
1 /*
2  * arch/sh64/kernel/switchto.S
3  *
4  * sh64 context switch
5  *
6  * Copyright (C) 2004  Richard Curnow
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11 */
12
13         .section .text..SHmedia32,"ax"
14         .little
15
16         .balign 32
17
18         .type sh64_switch_to,@function
19         .global sh64_switch_to
20         .global __sh64_switch_to_end
21 sh64_switch_to:
22
23 /* Incoming args
24    r2 - prev
25    r3 - &prev->thread
26    r4 - next
27    r5 - &next->thread
28
29    Outgoing results
30    r2 - last (=prev) : this just stays in r2 throughout
31
32    Want to create a full (struct pt_regs) on the stack to allow backtracing
33    functions to work.  However, we only need to populate the callee-save
34    register slots in this structure; since we're a function our ancestors must
35    have themselves preserved all caller saved state in the stack.  This saves
36    some wasted effort since we won't need to look at the values.
37
38    In particular, all caller-save registers are immediately available for
39    scratch use.
40
41 */
42
43 #define FRAME_SIZE (76*8 + 8)
44
45         movi    FRAME_SIZE, r0
46         sub.l   r15, r0, r15
47         ! Do normal-style register save to support backtrace
48
49         st.l    r15,   0, r18   ! save link reg
50         st.l    r15,   4, r14   ! save fp
51         add.l   r15, r63, r14   ! setup frame pointer
52
53         ! hopefully this looks normal to the backtrace now.
54
55         addi.l  r15,   8, r1    ! base of pt_regs
56         addi.l  r1,   24, r0    ! base of pt_regs.regs
57         addi.l  r0, (63*8), r8  ! base of pt_regs.trregs
58
59         /* Note : to be fixed?
60            struct pt_regs is really designed for holding the state on entry
61            to an exception, i.e. pc,sr,regs etc.  However, for the context
62            switch state, some of this is not required.  But the unwinder takes
63            struct pt_regs * as an arg so we have to build this structure
64            to allow unwinding switched tasks in show_state() */
65
66         st.q    r0, ( 9*8), r9
67         st.q    r0, (10*8), r10
68         st.q    r0, (11*8), r11
69         st.q    r0, (12*8), r12
70         st.q    r0, (13*8), r13
71         st.q    r0, (14*8), r14 ! for unwind, want to look as though we took a trap at
72         ! the point where the process is left in suspended animation, i.e. current
73         ! fp here, not the saved one.
74         st.q    r0, (16*8), r16
75
76         st.q    r0, (24*8), r24
77         st.q    r0, (25*8), r25
78         st.q    r0, (26*8), r26
79         st.q    r0, (27*8), r27
80         st.q    r0, (28*8), r28
81         st.q    r0, (29*8), r29
82         st.q    r0, (30*8), r30
83         st.q    r0, (31*8), r31
84         st.q    r0, (32*8), r32
85         st.q    r0, (33*8), r33
86         st.q    r0, (34*8), r34
87         st.q    r0, (35*8), r35
88
89         st.q    r0, (44*8), r44
90         st.q    r0, (45*8), r45
91         st.q    r0, (46*8), r46
92         st.q    r0, (47*8), r47
93         st.q    r0, (48*8), r48
94         st.q    r0, (49*8), r49
95         st.q    r0, (50*8), r50
96         st.q    r0, (51*8), r51
97         st.q    r0, (52*8), r52
98         st.q    r0, (53*8), r53
99         st.q    r0, (54*8), r54
100         st.q    r0, (55*8), r55
101         st.q    r0, (56*8), r56
102         st.q    r0, (57*8), r57
103         st.q    r0, (58*8), r58
104         st.q    r0, (59*8), r59
105
106         ! do this early as pta->gettr has no pipeline forwarding (=> 5 cycle latency)
107         ! Use a local label to avoid creating a symbol that will confuse the !
108         ! backtrace
109         pta     .Lsave_pc, tr0
110
111         gettr   tr5, r45
112         gettr   tr6, r46
113         gettr   tr7, r47
114         st.q    r8, (5*8), r45
115         st.q    r8, (6*8), r46
116         st.q    r8, (7*8), r47
117
118         ! Now switch context
119         gettr   tr0, r9
120         st.l    r3, 0, r15      ! prev->thread.sp
121         st.l    r3, 8, r1       ! prev->thread.kregs
122         st.l    r3, 4, r9       ! prev->thread.pc
123         st.q    r1, 0, r9       ! save prev->thread.pc into pt_regs->pc
124
125         ! Load PC for next task (init value or save_pc later)
126         ld.l    r5, 4, r18      ! next->thread.pc
127         ! Switch stacks
128         ld.l    r5, 0, r15      ! next->thread.sp
129         ptabs   r18, tr0
130
131         ! Update current
132         ld.l    r4, 4, r9       ! next->thread_info (2nd element of next task_struct)
133         putcon  r9, kcr0        ! current = next->thread_info
134
135         ! go to save_pc for a reschedule, or the initial thread.pc for a new process
136         blink   tr0, r63
137
138         ! Restore (when we come back to a previously saved task)
139 .Lsave_pc:
140         addi.l  r15, 32, r0     ! r0 = next's regs
141         addi.l  r0, (63*8), r8  ! r8 = next's tr_regs
142
143         ld.q    r8, (5*8), r45
144         ld.q    r8, (6*8), r46
145         ld.q    r8, (7*8), r47
146         ptabs   r45, tr5
147         ptabs   r46, tr6
148         ptabs   r47, tr7
149
150         ld.q    r0, ( 9*8), r9
151         ld.q    r0, (10*8), r10
152         ld.q    r0, (11*8), r11
153         ld.q    r0, (12*8), r12
154         ld.q    r0, (13*8), r13
155         ld.q    r0, (14*8), r14
156         ld.q    r0, (16*8), r16
157
158         ld.q    r0, (24*8), r24
159         ld.q    r0, (25*8), r25
160         ld.q    r0, (26*8), r26
161         ld.q    r0, (27*8), r27
162         ld.q    r0, (28*8), r28
163         ld.q    r0, (29*8), r29
164         ld.q    r0, (30*8), r30
165         ld.q    r0, (31*8), r31
166         ld.q    r0, (32*8), r32
167         ld.q    r0, (33*8), r33
168         ld.q    r0, (34*8), r34
169         ld.q    r0, (35*8), r35
170
171         ld.q    r0, (44*8), r44
172         ld.q    r0, (45*8), r45
173         ld.q    r0, (46*8), r46
174         ld.q    r0, (47*8), r47
175         ld.q    r0, (48*8), r48
176         ld.q    r0, (49*8), r49
177         ld.q    r0, (50*8), r50
178         ld.q    r0, (51*8), r51
179         ld.q    r0, (52*8), r52
180         ld.q    r0, (53*8), r53
181         ld.q    r0, (54*8), r54
182         ld.q    r0, (55*8), r55
183         ld.q    r0, (56*8), r56
184         ld.q    r0, (57*8), r57
185         ld.q    r0, (58*8), r58
186         ld.q    r0, (59*8), r59
187
188         ! epilogue
189         ld.l    r15, 0, r18
190         ld.l    r15, 4, r14
191         ptabs   r18, tr0
192         movi    FRAME_SIZE, r0
193         add     r15, r0, r15
194         blink   tr0, r63
195 __sh64_switch_to_end:
196 .LFE1:
197         .size   sh64_switch_to,.LFE1-sh64_switch_to
198