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