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 196