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