sh: NO_CONTEXT ASID optimizations for SH-4 cache flush.
[linux-block.git] / arch / sh / kernel / cpu / sh3 / entry.S
CommitLineData
baf4326e 1/*
58862699 2 * arch/sh/kernel/cpu/sh3/entry.S
1da177e4
LT
3 *
4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
baf4326e 5 * Copyright (C) 2003 - 2006 Paul Mundt
1da177e4
LT
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
1da177e4 10 */
1da177e4 11#include <linux/sys.h>
711fa809 12#include <linux/errno.h>
1da177e4 13#include <linux/linkage.h>
1da177e4
LT
14#include <asm/asm-offsets.h>
15#include <asm/thread_info.h>
db2e1fa3 16#include <asm/unistd.h>
f15cbe6f 17#include <cpu/mmu_context.h>
1efe4ce3 18#include <asm/page.h>
1d015cf0 19#include <asm/cache.h>
1da177e4 20
1da177e4
LT
21! NOTE:
22! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
23! to be jumped is too far, but it causes illegal slot exception.
24
25/*
26 * entry.S contains the system-call and fault low-level handling routines.
27 * This also contains the timer-interrupt handler, as well as all interrupts
28 * and faults that can result in a task-switch.
29 *
30 * NOTE: This code handles signal-recognition, which happens every time
31 * after a timer-interrupt and after each system call.
32 *
33 * NOTE: This code uses a convention that instructions in the delay slot
34 * of a transfer-control instruction are indented by an extra space, thus:
35 *
36 * jmp @k0 ! control-transfer instruction
37 * ldc k1, ssr ! delay slot
38 *
39 * Stack layout in 'ret_from_syscall':
40 * ptrace needs to have all regs on the stack.
41 * if the order here is changed, it needs to be
42 * updated in ptrace.c and ptrace.h
43 *
44 * r0
45 * ...
46 * r15 = stack pointer
47 * spc
48 * pr
49 * ssr
50 * gbr
51 * mach
52 * macl
53 * syscall #
54 *
55 */
ab6e570b 56#if defined(CONFIG_KGDB)
1da177e4
LT
57NMI_VEC = 0x1c0 ! Must catch early for debounce
58#endif
59
60/* Offsets to the stack */
61OFF_R0 = 0 /* Return value. New ABI also arg4 */
62OFF_R1 = 4 /* New ABI: arg5 */
63OFF_R2 = 8 /* New ABI: arg6 */
64OFF_R3 = 12 /* New ABI: syscall_nr */
65OFF_R4 = 16 /* New ABI: arg0 */
66OFF_R5 = 20 /* New ABI: arg1 */
67OFF_R6 = 24 /* New ABI: arg2 */
68OFF_R7 = 28 /* New ABI: arg3 */
69OFF_SP = (15*4)
70OFF_PC = (16*4)
71OFF_SR = (16*4+8)
72OFF_TRA = (16*4+6*4)
73
74
75#define k0 r0
76#define k1 r1
77#define k2 r2
78#define k3 r3
79#define k4 r4
80
1da177e4
LT
81#define g_imask r6 /* r6_bank1 */
82#define k_g_imask r6_bank /* r6_bank1 */
83#define current r7 /* r7_bank1 */
84
de398406
YS
85#include <asm/entry-macros.S>
86
1da177e4
LT
87/*
88 * Kernel mode register usage:
89 * k0 scratch
90 * k1 scratch
91 * k2 scratch (Exception code)
92 * k3 scratch (Return address)
93 * k4 scratch
94 * k5 reserved
95 * k6 Global Interrupt Mask (0--15 << 4)
96 * k7 CURRENT_THREAD_INFO (pointer to current thread info)
97 */
98
99!
100! TLB Miss / Initial Page write exception handling
101! _and_
102! TLB hits, but the access violate the protection.
103! It can be valid access, such as stack grow and/or C-O-W.
104!
105!
106! Find the pmd/pte entry and loadtlb
107! If it's not found, cause address error (SEGV)
108!
109! Although this could be written in assembly language (and it'd be faster),
110! this first version depends *much* on C implementation.
111!
112
1da177e4
LT
113#if defined(CONFIG_MMU)
114 .align 2
115ENTRY(tlb_miss_load)
116 bra call_dpf
117 mov #0, r5
118
119 .align 2
120ENTRY(tlb_miss_store)
121 bra call_dpf
122 mov #1, r5
123
124 .align 2
125ENTRY(initial_page_write)
126 bra call_dpf
127 mov #1, r5
128
129 .align 2
130ENTRY(tlb_protection_violation_load)
131 bra call_dpf
132 mov #0, r5
133
134 .align 2
135ENTRY(tlb_protection_violation_store)
136 bra call_dpf
137 mov #1, r5
138
139call_dpf:
140 mov.l 1f, r0
db2e1fa3
PM
141 mov r5, r8
142 mov.l @r0, r6
143 mov r6, r9
144 mov.l 2f, r0
145 sts pr, r10
146 jsr @r0
147 mov r15, r4
148 !
149 tst r0, r0
150 bf/s 0f
151 lds r10, pr
152 rts
153 nop
c347d12c 1540: mov.l 3f, r0
db2e1fa3
PM
155 mov r9, r6
156 mov r8, r5
1da177e4 157 jmp @r0
db2e1fa3 158 mov r15, r4
1da177e4
LT
159
160 .align 2
1611: .long MMU_TEA
db2e1fa3 1622: .long __do_page_fault
1da177e4
LT
1633: .long do_page_fault
164
165 .align 2
166ENTRY(address_error_load)
167 bra call_dae
168 mov #0,r5 ! writeaccess = 0
169
170 .align 2
171ENTRY(address_error_store)
172 bra call_dae
173 mov #1,r5 ! writeaccess = 1
174
175 .align 2
176call_dae:
177 mov.l 1f, r0
178 mov.l @r0, r6 ! address
179 mov.l 2f, r0
180 jmp @r0
181 mov r15, r4 ! regs
182
183 .align 2
1841: .long MMU_TEA
1852: .long do_address_error
186#endif /* CONFIG_MMU */
187
1da177e4
LT
188#if defined(CONFIG_SH_STANDARD_BIOS)
189 /* Unwind the stack and jmp to the debug entry */
f413d0d9 190ENTRY(sh_bios_handler)
1dd22722
MD
191 mov.l 1f, r8
192 bsr restore_regs
193 nop
194
195 lds k2, pr ! restore pr
196 mov k4, r15
1da177e4
LT
197 !
198 mov.l 2f, k0
199 mov.l @k0, k0
200 jmp @k0
1dd22722 201 ldc k3, ssr
1da177e4
LT
202 .align 2
2031: .long 0x300000f0
2042: .long gdb_vbr_vector
205#endif /* CONFIG_SH_STANDARD_BIOS */
206
1dd22722
MD
207! restore_regs()
208! - restore r0, r1, r2, r3, r4, r5, r6, r7 from the stack
209! - switch bank
210! - restore r8, r9, r10, r11, r12, r13, r14, r15 from the stack
211! - restore spc, pr*, ssr, gbr, mach, macl, skip default tra
212! k2 returns original pr
213! k3 returns original sr
214! k4 returns original stack pointer
215! r8 passes SR bitmask, overwritten with restored data on return
216! r9 trashed
217! BL=0 on entry, on exit BL=1 (depending on r8).
218
2ef7f0da 219ENTRY(restore_regs)
1da177e4
LT
220 mov.l @r15+, r0
221 mov.l @r15+, r1
222 mov.l @r15+, r2
223 mov.l @r15+, r3
224 mov.l @r15+, r4
225 mov.l @r15+, r5
226 mov.l @r15+, r6
227 mov.l @r15+, r7
228 !
1dd22722
MD
229 stc sr, r9
230 or r8, r9
231 ldc r9, sr
1da177e4
LT
232 !
233 mov.l @r15+, r8
234 mov.l @r15+, r9
235 mov.l @r15+, r10
236 mov.l @r15+, r11
237 mov.l @r15+, r12
238 mov.l @r15+, r13
239 mov.l @r15+, r14
240 mov.l @r15+, k4 ! original stack pointer
241 ldc.l @r15+, spc
1dd22722 242 mov.l @r15+, k2 ! original PR
1da177e4
LT
243 mov.l @r15+, k3 ! original SR
244 ldc.l @r15+, gbr
245 lds.l @r15+, mach
246 lds.l @r15+, macl
1dd22722
MD
247 rts
248 add #4, r15 ! Skip syscall number
249
250restore_all:
251 mov.l 7f, r8
252 bsr restore_regs
253 nop
254
255 lds k2, pr ! restore pr
1da177e4 256 !
1da177e4
LT
257 ! Calculate new SR value
258 mov k3, k2 ! original SR value
de398406
YS
259 mov #0xf0, k1
260 extu.b k1, k1
261 not k1, k1
1d015cf0 262 and k1, k2 ! Mask original SR value
1da177e4
LT
263 !
264 mov k3, k0 ! Calculate IMASK-bits
265 shlr2 k0
266 and #0x3c, k0
267 cmp/eq #0x3c, k0
268 bt/s 6f
269 shll2 k0
270 mov g_imask, k0
271 !
2726: or k0, k2 ! Set the IMASK-bits
273 ldc k2, ssr
274 !
ab6e570b 275#if defined(CONFIG_KGDB)
1da177e4 276 ! Clear in_nmi
6ae5e8d7 277 mov.l 6f, k0
1da177e4
LT
278 mov #0, k1
279 mov.b k1, @k0
280#endif
1da177e4
LT
281 mov k4, r15
282 rte
283 nop
284
285 .align 2
1da177e4 2865: .long 0x00001000 ! DSP
ab6e570b 287#ifdef CONFIG_KGDB
370ac91a 2886: .long in_nmi
c596b1a3 289#endif
1da177e4 2907: .long 0x30000000
1da177e4 291
de398406 292! common exception handler
716067f2 293#include "../../entry-common.S"
de398406 294
1da177e4
LT
295! Exception Vector Base
296!
297! Should be aligned page boundary.
298!
299 .balign 4096,0,4096
300ENTRY(vbr_base)
301 .long 0
1d015cf0
MD
302!
303! 0x100: General exception vector
1da177e4
LT
304!
305 .balign 256,0,256
306general_exception:
1d015cf0
MD
307#ifndef CONFIG_CPU_SUBTYPE_SHX3
308 bra handle_exception
309 sts pr, k3 ! save original pr value in k3
310#else
311 mov.l 1f, k4
312 mov.l @k4, k4
2b1bd1ac
PM
313
314 ! Is EXPEVT larger than 0x800?
315 mov #0x8, k0
316 shll8 k0
1d015cf0 317 cmp/hs k0, k4
2b1bd1ac
PM
318 bf 0f
319
320 ! then add 0x580 (k2 is 0xd80 or 0xda0)
321 mov #0x58, k0
322 shll2 k0
323 shll2 k0
1d015cf0 324 add k0, k4
2b1bd1ac 3250:
1d015cf0 326 ! Setup stack and save DSP context (k0 contains original r15 on return)
01ab1039 327 bsr prepare_stack
2b1bd1ac 328 nop
9b3a53ab 329
1d015cf0 330 ! Save registers / Switch to bank 0
7a516280 331 mov k4, k2 ! keep vector in k2
2ef7f0da 332 mov.l 1f, k4 ! SR bits to clear in k4
1d015cf0 333 bsr save_regs ! needs original pr value in k3
2ef7f0da 334 nop
1d015cf0
MD
335
336 bra handle_exception_special
1da177e4 337 nop
1da177e4
LT
338
339 .align 2
3401: .long EXPEVT
1d015cf0 341#endif
1da177e4 342
01ab1039 343! prepare_stack()
1d015cf0
MD
344! - roll back gRB
345! - switch to kernel stack
1d015cf0
MD
346! k0 returns original sp (after roll back)
347! k1 trashed
348! k2 trashed
1efe4ce3 349
01ab1039 350prepare_stack:
1efe4ce3
SM
351#ifdef CONFIG_GUSA
352 ! Check for roll back gRB (User and Kernel)
353 mov r15, k0
354 shll k0
355 bf/s 1f
356 shll k0
357 bf/s 1f
358 stc spc, k1
359 stc r0_bank, k0
360 cmp/hs k0, k1 ! test k1 (saved PC) >= k0 (saved r0)
361 bt/s 2f
362 stc r1_bank, k1
363
364 add #-2, k0
365 add r15, k0
366 ldc k0, spc ! PC = saved r0 + r15 - 2
3672: mov k1, r15 ! SP = r1
3681:
369#endif
1d015cf0 370 ! Switch to kernel stack if needed
1da177e4
LT
371 stc ssr, k0 ! Is it from kernel space?
372 shll k0 ! Check MD bit (bit30) by shifting it into...
373 shll k0 ! ...the T bit
374 bt/s 1f ! It's a kernel to kernel transition.
375 mov r15, k0 ! save original stack to k0
376 /* User space to kernel */
510c72ad 377 mov #(THREAD_SIZE >> 10), k1
a6a31139 378 shll8 k1 ! k1 := THREAD_SIZE
510c72ad 379 shll2 k1
1da177e4
LT
380 add current, k1
381 mov k1, r15 ! change to kernel stack
382 !
1d015cf0 3831:
1d015cf0
MD
384 rts
385 nop
01ab1039 386
1d015cf0
MD
387!
388! 0x400: Instruction and Data TLB miss exception vector
389!
390 .balign 1024,0,1024
391tlb_miss:
392 sts pr, k3 ! save original pr value in k3
baf4326e 393
1d015cf0 394handle_exception:
0197f21c
MD
395 mova exception_data, k0
396
1d015cf0 397 ! Setup stack and save DSP context (k0 contains original r15 on return)
01ab1039 398 bsr prepare_stack
0197f21c 399 PREF(k0)
1d015cf0
MD
400
401 ! Save registers / Switch to bank 0
402 mov.l 5f, k2 ! vector register address
2ef7f0da 403 mov.l 1f, k4 ! SR bits to clear in k4
1d015cf0
MD
404 bsr save_regs ! needs original pr value in k3
405 mov.l @k2, k2 ! read out vector and keep in k2
406
407handle_exception_special:
408 ! Setup return address and jump to exception handler
409 mov.l 7f, r9 ! fetch return address
410 stc r2_bank, r0 ! k2 (vector)
411 mov.l 6f, r10
412 shlr2 r0
413 shlr r0
414 mov.l @(r0, r10), r10
415 jmp @r10
416 lds r9, pr ! put return address in pr
417
418 .align L1_CACHE_SHIFT
419
420! save_regs()
4f099ebb 421! - save default tra, macl, mach, gbr, ssr, pr* and spc on the stack
1d015cf0
MD
422! - save r15*, r14, r13, r12, r11, r10, r9, r8 on the stack
423! - switch bank
424! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
425! k0 contains original stack pointer*
426! k1 trashed
1d015cf0 427! k3 passes original pr*
2ef7f0da 428! k4 passes SR bitmask
1d015cf0
MD
429! BL=1 on entry, on exit BL=0.
430
2ef7f0da 431ENTRY(save_regs)
1d015cf0 432 mov #-1, r1
1d015cf0 433 mov.l k1, @-r15 ! set TRA (default: -1)
1da177e4
LT
434 sts.l macl, @-r15
435 sts.l mach, @-r15
436 stc.l gbr, @-r15
437 stc.l ssr, @-r15
1d015cf0 438 mov.l k3, @-r15 ! original pr in k3
1da177e4 439 stc.l spc, @-r15
1d015cf0
MD
440
441 mov.l k0, @-r15 ! original stack pointer in k0
1da177e4
LT
442 mov.l r14, @-r15
443 mov.l r13, @-r15
444 mov.l r12, @-r15
445 mov.l r11, @-r15
446 mov.l r10, @-r15
447 mov.l r9, @-r15
448 mov.l r8, @-r15
1d015cf0
MD
449
450 mov.l 0f, k3 ! SR bits to set in k3
1d015cf0 451
2ef7f0da
MD
452 ! fall-through
453
454! save_low_regs()
455! - modify SR for bank switch
456! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
457! k3 passes bits to set in SR
458! k4 passes bits to clear in SR
459
460ENTRY(save_low_regs)
1d015cf0
MD
461 stc sr, r8
462 or k3, r8
463 and k4, r8
464 ldc r8, sr
465
1da177e4
LT
466 mov.l r7, @-r15
467 mov.l r6, @-r15
468 mov.l r5, @-r15
469 mov.l r4, @-r15
470 mov.l r3, @-r15
471 mov.l r2, @-r15
472 mov.l r1, @-r15
baf4326e 473 rts
1d015cf0 474 mov.l r0, @-r15
1da177e4 475
1d015cf0
MD
476!
477! 0x600: Interrupt / NMI vector
478!
479 .balign 512,0,512
480ENTRY(handle_interrupt)
481#if defined(CONFIG_KGDB)
482 mov.l 2f, k2
483 ! Debounce (filter nested NMI)
484 mov.l @k2, k0
485 mov.l 9f, k1
486 cmp/eq k1, k0
487 bf 11f
488 mov.l 10f, k1
489 tas.b @k1
490 bt 11f
491 rte
492 nop
1da177e4 493 .align 2
1d015cf0
MD
4949: .long NMI_VEC
49510: .long in_nmi
49611:
497#endif /* defined(CONFIG_KGDB) */
498 sts pr, k3 ! save original pr value in k3
0197f21c 499 mova exception_data, k0
1da177e4 500
1d015cf0 501 ! Setup stack and save DSP context (k0 contains original r15 on return)
01ab1039 502 bsr prepare_stack
0197f21c 503 PREF(k0)
baf4326e 504
1d015cf0 505 ! Save registers / Switch to bank 0
2ef7f0da 506 mov.l 1f, k4 ! SR bits to clear in k4
1d015cf0
MD
507 bsr save_regs ! needs original pr value in k3
508 mov #-1, k2 ! default vector kept in k2
509
510 ! Setup return address and jump to do_IRQ
511 mov.l 4f, r9 ! fetch return address
512 lds r9, pr ! put return address in pr
513 mov.l 2f, r4
514 mov.l 3f, r9
515 mov.l @r4, r4 ! pass INTEVT vector as arg0
516 jmp @r9
517 mov r15, r5 ! pass saved registers as arg1
baf4326e 518
1da177e4
LT
519ENTRY(exception_none)
520 rts
521 nop
1d015cf0
MD
522
523 .align L1_CACHE_SHIFT
524exception_data:
5250: .long 0x000080f0 ! FD=1, IMASK=15
5261: .long 0xcfffffff ! RB=0, BL=0
5272: .long INTEVT
5283: .long do_IRQ
5294: .long ret_from_irq
5305: .long EXPEVT
5316: .long exception_handling_table
5327: .long ret_from_exception