1/* SPDX-License-Identifier: GPL-2.0
2 *
3 * arch/sh/kernel/cpu/sh2/entry.S
4 *
5 * The SH-2 exception entry
6 *
7 * Copyright (C) 2005-2008 Yoshinori Sato
8 * Copyright (C) 2005 AXE,Inc.
9 */
10
11#include <linux/linkage.h>
12#include <asm/asm-offsets.h>
13#include <asm/thread_info.h>
14#include <cpu/mmu_context.h>
15#include <asm/unistd.h>
16#include <asm/errno.h>
17#include <asm/page.h>
18
19/* Offsets to the stack */
20OFF_R0 = 0 /* Return value. New ABI also arg4 */
21OFF_R1 = 4 /* New ABI: arg5 */
22OFF_R2 = 8 /* New ABI: arg6 */
23OFF_R3 = 12 /* New ABI: syscall_nr */
24OFF_R4 = 16 /* New ABI: arg0 */
25OFF_R5 = 20 /* New ABI: arg1 */
26OFF_R6 = 24 /* New ABI: arg2 */
27OFF_R7 = 28 /* New ABI: arg3 */
28OFF_SP = (15*4)
29OFF_PC = (16*4)
30OFF_SR = (16*4+2*4)
31OFF_TRA = (16*4+6*4)
32
33#include <asm/entry-macros.S>
34
35ENTRY(exception_handler)
36 ! stack
37 ! r0 <- point sp
38 ! r1
39 ! pc
40 ! sr
41 ! r0 = temporary
42 ! r1 = vector (pseudo EXPEVT / INTEVT / TRA)
43 mov.l r2,@-sp
44 mov.l r3,@-sp
45 cli
46 mov.l $cpu_mode,r2
47#ifdef CONFIG_SMP
48 mov.l $cpuid,r3
49 mov.l @r3,r3
50 mov.l @r3,r3
51 shll2 r3
52 add r3,r2
53#endif
54 mov.l @r2,r0
55 mov.l @(5*4,r15),r3 ! previous SR
56 or r0,r3 ! set MD
57 tst r0,r0
58 bf/s 1f ! previous mode check
59 mov.l r3,@(5*4,r15) ! update SR
60 ! switch to kernel mode
61 mov.l __md_bit,r0
62 mov.l r0,@r2 ! enter kernel mode
63 mov.l $current_thread_info,r2
64#ifdef CONFIG_SMP
65 mov.l $cpuid,r0
66 mov.l @r0,r0
67 mov.l @r0,r0
68 shll2 r0
69 add r0,r2
70#endif
71 mov.l @r2,r2
72 mov #(THREAD_SIZE >> 8),r0
73 shll8 r0
74 add r2,r0
75 mov r15,r2 ! r2 = user stack top
76 mov r0,r15 ! switch kernel stack
77 mov.l r1,@-r15 ! TRA
78 sts.l macl, @-r15
79 sts.l mach, @-r15
80 stc.l gbr, @-r15
81 mov.l @(5*4,r2),r0
82 mov.l r0,@-r15 ! original SR
83 sts.l pr,@-r15
84 mov.l @(4*4,r2),r0
85 mov.l r0,@-r15 ! original PC
86 mov r2,r3
87 add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame
88 mov.l r3,@-r15 ! original SP
89 mov.l r14,@-r15
90 mov.l r13,@-r15
91 mov.l r12,@-r15
92 mov.l r11,@-r15
93 mov.l r10,@-r15
94 mov.l r9,@-r15
95 mov.l r8,@-r15
96 mov.l r7,@-r15
97 mov.l r6,@-r15
98 mov.l r5,@-r15
99 mov.l r4,@-r15
100 mov r1,r9 ! save TRA
101 mov r2,r8 ! copy user -> kernel stack
102 mov.l @(0,r8),r3
103 mov.l r3,@-r15
104 mov.l @(4,r8),r2
105 mov.l r2,@-r15
106 mov.l @(12,r8),r1
107 mov.l r1,@-r15
108 mov.l @(8,r8),r0
109 bra 2f
110 mov.l r0,@-r15
1111:
112 ! in kernel exception
113 mov #(22-4-4-1)*4+4,r0
114 mov r15,r2
115 sub r0,r15
116 mov.l @r2+,r0 ! old R3
117 mov.l r0,@-r15
118 mov.l @r2+,r0 ! old R2
119 mov.l r0,@-r15
120 mov.l @(4,r2),r0 ! old R1
121 mov.l r0,@-r15
122 mov.l @r2,r0 ! old R0
123 mov.l r0,@-r15
124 add #8,r2
125 mov.l @r2+,r3 ! old PC
126 mov.l @r2+,r0 ! old SR
127 add #-4,r2 ! exception frame stub (sr)
128 mov.l r1,@-r2 ! TRA
129 sts.l macl, @-r2
130 sts.l mach, @-r2
131 stc.l gbr, @-r2
132 mov.l r0,@-r2 ! save old SR
133 sts.l pr,@-r2
134 mov.l r3,@-r2 ! save old PC
135 mov r2,r0
136 add #8*4,r0
137 mov.l r0,@-r2 ! save old SP
138 mov.l r14,@-r2
139 mov.l r13,@-r2
140 mov.l r12,@-r2
141 mov.l r11,@-r2
142 mov.l r10,@-r2
143 mov.l r9,@-r2
144 mov.l r8,@-r2
145 mov.l r7,@-r2
146 mov.l r6,@-r2
147 mov.l r5,@-r2
148 mov.l r4,@-r2
149 mov r1,r9
150 mov.l @(OFF_R0,r15),r0
151 mov.l @(OFF_R1,r15),r1
152 mov.l @(OFF_R2,r15),r2
153 mov.l @(OFF_R3,r15),r3
1542:
155 mov #64,r8
156 cmp/hs r8,r9
157 bt interrupt_entry ! vec >= 64 is interrupt
158 mov #31,r8
159 cmp/hs r8,r9
160 bt trap_entry ! 64 > vec >= 31 is trap
161#ifdef CONFIG_CPU_J2
162 mov #16,r8
163 cmp/hs r8,r9
164 bt interrupt_entry ! 31 > vec >= 16 is interrupt
165#endif
166
167 mov.l 4f,r8
168 mov r9,r4
169 shll2 r9
170 add r9,r8
171 mov.l @r8,r8 ! exception handler address
172 tst r8,r8
173 bf 3f
174 mov.l 8f,r8 ! unhandled exception
1753:
176 mov.l 5f,r10
177 jmp @r8
178 lds r10,pr
179
180interrupt_entry:
181 mov r9,r4
182 mov r15,r5
183 mov.l 6f,r9
184 mov.l 7f,r8
185 jmp @r8
186 lds r9,pr
187
188 .align 2
1894: .long exception_handling_table
1905: .long ret_from_exception
1916: .long ret_from_irq
1927: .long do_IRQ
1938: .long exception_error
194
195trap_entry:
196 mov #0x30,r8
197 cmp/ge r8,r9 ! vector 0x1f-0x2f is systemcall
198 bt 1f
199 mov #0x1f,r9 ! convert to unified SH2/3/4 trap number
2001:
201 shll2 r9 ! TRA
202 bra system_call ! jump common systemcall entry
203 mov r9,r8
204
205#if defined(CONFIG_SH_STANDARD_BIOS)
206 /* Unwind the stack and jmp to the debug entry */
207ENTRY(sh_bios_handler)
208 mov r15,r0
209 add #(22-4)*4-4,r0
210 ldc.l @r0+,gbr
211 lds.l @r0+,mach
212 lds.l @r0+,macl
213 mov r15,r0
214 mov.l @(OFF_SP,r0),r1
215 mov #OFF_SR,r2
216 mov.l @(r0,r2),r3
217 mov.l r3,@-r1
218 mov #OFF_SP,r2
219 mov.l @(r0,r2),r3
220 mov.l r3,@-r1
221 mov r15,r0
222 add #(22-4)*4-8,r0
223 mov.l 1f,r2
224 mov.l @r2,r2
225 stc sr,r3
226 mov.l r2,@r0
227 mov.l r3,@(4,r0)
228 mov.l r1,@(8,r0)
229 mov.l @r15+, r0
230 mov.l @r15+, r1
231 mov.l @r15+, r2
232 mov.l @r15+, r3
233 mov.l @r15+, r4
234 mov.l @r15+, r5
235 mov.l @r15+, r6
236 mov.l @r15+, r7
237 mov.l @r15+, r8
238 mov.l @r15+, r9
239 mov.l @r15+, r10
240 mov.l @r15+, r11
241 mov.l @r15+, r12
242 mov.l @r15+, r13
243 mov.l @r15+, r14
244 add #8,r15
245 lds.l @r15+, pr
246 mov.l @r15+,r15
247 rte
248 nop
249 .align 2
2501: .long gdb_vbr_vector
251#endif /* CONFIG_SH_STANDARD_BIOS */
252
253ENTRY(address_error_trap_handler)
254 mov r15,r4 ! regs
255 mov #OFF_PC,r0
256 mov.l @(r0,r15),r6 ! pc
257 mov.l 1f,r0
258 jmp @r0
259 mov #0,r5 ! writeaccess is unknown
260
261 .align 2
2621: .long do_address_error
263
264restore_all:
265 stc sr,r0
266 or #0xf0,r0
267 ldc r0,sr ! all interrupt block (same BL = 1)
268 ! restore special register
269 ! overlap exception frame
270 mov r15,r0
271 add #17*4,r0
272 lds.l @r0+,pr
273 add #4,r0
274 ldc.l @r0+,gbr
275 lds.l @r0+,mach
276 lds.l @r0+,macl
277 mov r15,r0
278 mov.l $cpu_mode,r2
279#ifdef CONFIG_SMP
280 mov.l $cpuid,r3
281 mov.l @r3,r3
282 mov.l @r3,r3
283 shll2 r3
284 add r3,r2
285#endif
286 mov #OFF_SR,r3
287 mov.l @(r0,r3),r1
288 mov.l __md_bit,r3
289 and r1,r3 ! copy MD bit
290 mov.l r3,@r2
291 shll2 r1 ! clear MD bit
292 shlr2 r1
293 mov.l @(OFF_SP,r0),r2
294 add #-8,r2
295 mov.l r2,@(OFF_SP,r0) ! point exception frame top
296 mov.l r1,@(4,r2) ! set sr
297 mov #OFF_PC,r3
298 mov.l @(r0,r3),r1
299 mov.l r1,@r2 ! set pc
300 get_current_thread_info r0, r1
301 mov.l $current_thread_info,r1
302#ifdef CONFIG_SMP
303 mov.l $cpuid,r3
304 mov.l @r3,r3
305 mov.l @r3,r3
306 shll2 r3
307 add r3,r1
308#endif
309 mov.l r0,@r1
310 mov.l @r15+,r0
311 mov.l @r15+,r1
312 mov.l @r15+,r2
313 mov.l @r15+,r3
314 mov.l @r15+,r4
315 mov.l @r15+,r5
316 mov.l @r15+,r6
317 mov.l @r15+,r7
318 mov.l @r15+,r8
319 mov.l @r15+,r9
320 mov.l @r15+,r10
321 mov.l @r15+,r11
322 mov.l @r15+,r12
323 mov.l @r15+,r13
324 mov.l @r15+,r14
325 mov.l @r15,r15
326 rte
327 nop
328
329 .align 2
330__md_bit:
331 .long 0x40000000
332$current_thread_info:
333 .long __current_thread_info
334$cpu_mode:
335 .long __cpu_mode
336#ifdef CONFIG_SMP
337$cpuid:
338 .long sh2_cpuid_addr
339#endif
340
341! common exception handler
342#include "../../entry-common.S"
343
344#ifdef CONFIG_NR_CPUS
345#define NR_CPUS CONFIG_NR_CPUS
346#else
347#define NR_CPUS 1
348#endif
349
350 .data
351! cpu operation mode
352! bit30 = MD (compatible SH3/4)
353__cpu_mode:
354 .rept NR_CPUS
355 .long 0x40000000
356 .endr
357
358#ifdef CONFIG_SMP
359.global sh2_cpuid_addr
360sh2_cpuid_addr:
361 .long dummy_cpuid
362dummy_cpuid:
363 .long 0
364#endif
365
366 .section .bss
367__current_thread_info:
368 .rept NR_CPUS
369 .long 0
370 .endr
371
372ENTRY(exception_handling_table)
373 .space 4*32
374

source code of linux/arch/sh/kernel/cpu/sh2/entry.S