GNU Linux-libre 6.7.9-gnu
[releases.git] / arch / sh / kernel / cpu / sh2 / entry.S
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 */
20 OFF_R0  =  0            /* Return value. New ABI also arg4 */
21 OFF_R1  =  4            /* New ABI: arg5 */
22 OFF_R2  =  8            /* New ABI: arg6 */
23 OFF_R3  =  12           /* New ABI: syscall_nr */
24 OFF_R4  =  16           /* New ABI: arg0 */
25 OFF_R5  =  20           /* New ABI: arg1 */
26 OFF_R6  =  24           /* New ABI: arg2 */
27 OFF_R7  =  28           /* New ABI: arg3 */
28 OFF_SP  =  (15*4)
29 OFF_PC  =  (16*4)
30 OFF_SR  =  (16*4+2*4)
31 OFF_TRA =  (16*4+6*4)
32
33 #include <asm/entry-macros.S>
34
35 ENTRY(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
111 1:
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
154 2:
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
175 3:
176         mov.l   5f,r10
177         jmp     @r8
178          lds    r10,pr
179
180 interrupt_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
189 4:      .long   exception_handling_table
190 5:      .long   ret_from_exception
191 6:      .long   ret_from_irq
192 7:      .long   do_IRQ
193 8:      .long   exception_error
194
195 trap_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
200 1:      
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 */
207 ENTRY(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
250 1:      .long   gdb_vbr_vector
251 #endif /* CONFIG_SH_STANDARD_BIOS */
252
253 ENTRY(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
262 1:      .long   do_address_error
263
264 restore_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
360 sh2_cpuid_addr:
361         .long   dummy_cpuid
362 dummy_cpuid:
363         .long   0
364 #endif
365                 
366         .section        .bss
367 __current_thread_info:
368         .rept   NR_CPUS
369         .long   0
370         .endr
371
372 ENTRY(exception_handling_table)
373         .space  4*32