entry.S 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
  2. *
  3. * linux/arch/sh/entry.S
  4. *
  5. * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
  6. * Copyright (C) 2003 Paul Mundt
  7. *
  8. * This file is subject to the terms and conditions of the GNU General Public
  9. * License. See the file "COPYING" in the main directory of this archive
  10. * for more details.
  11. *
  12. */
  13. #include <linux/sys.h>
  14. #include <linux/linkage.h>
  15. #include <asm/asm-offsets.h>
  16. #include <asm/thread_info.h>
  17. #include <asm/cpu/mmu_context.h>
  18. #include <asm/unistd.h>
  19. #if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
  20. #define sys_nfsservctl sys_ni_syscall
  21. #endif
  22. #if !defined(CONFIG_MMU)
  23. #define sys_madvise sys_ni_syscall
  24. #define sys_readahead sys_ni_syscall
  25. #define sys_mprotect sys_ni_syscall
  26. #define sys_msync sys_ni_syscall
  27. #define sys_mlock sys_ni_syscall
  28. #define sys_munlock sys_ni_syscall
  29. #define sys_mlockall sys_ni_syscall
  30. #define sys_munlockall sys_ni_syscall
  31. #define sys_mremap sys_ni_syscall
  32. #define sys_mincore sys_ni_syscall
  33. #define sys_remap_file_pages sys_ni_syscall
  34. #endif
  35. ! NOTE:
  36. ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
  37. ! to be jumped is too far, but it causes illegal slot exception.
  38. /*
  39. * entry.S contains the system-call and fault low-level handling routines.
  40. * This also contains the timer-interrupt handler, as well as all interrupts
  41. * and faults that can result in a task-switch.
  42. *
  43. * NOTE: This code handles signal-recognition, which happens every time
  44. * after a timer-interrupt and after each system call.
  45. *
  46. * NOTE: This code uses a convention that instructions in the delay slot
  47. * of a transfer-control instruction are indented by an extra space, thus:
  48. *
  49. * jmp @k0 ! control-transfer instruction
  50. * ldc k1, ssr ! delay slot
  51. *
  52. * Stack layout in 'ret_from_syscall':
  53. * ptrace needs to have all regs on the stack.
  54. * if the order here is changed, it needs to be
  55. * updated in ptrace.c and ptrace.h
  56. *
  57. * r0
  58. * ...
  59. * r15 = stack pointer
  60. * spc
  61. * pr
  62. * ssr
  63. * gbr
  64. * mach
  65. * macl
  66. * syscall #
  67. *
  68. */
  69. ENOSYS = 38
  70. EINVAL = 22
  71. #if defined(CONFIG_KGDB_NMI)
  72. NMI_VEC = 0x1c0 ! Must catch early for debounce
  73. #endif
  74. /* Offsets to the stack */
  75. OFF_R0 = 0 /* Return value. New ABI also arg4 */
  76. OFF_R1 = 4 /* New ABI: arg5 */
  77. OFF_R2 = 8 /* New ABI: arg6 */
  78. OFF_R3 = 12 /* New ABI: syscall_nr */
  79. OFF_R4 = 16 /* New ABI: arg0 */
  80. OFF_R5 = 20 /* New ABI: arg1 */
  81. OFF_R6 = 24 /* New ABI: arg2 */
  82. OFF_R7 = 28 /* New ABI: arg3 */
  83. OFF_SP = (15*4)
  84. OFF_PC = (16*4)
  85. OFF_SR = (16*4+8)
  86. OFF_TRA = (16*4+6*4)
  87. #define k0 r0
  88. #define k1 r1
  89. #define k2 r2
  90. #define k3 r3
  91. #define k4 r4
  92. #define k_ex_code r2_bank /* r2_bank1 */
  93. #define g_imask r6 /* r6_bank1 */
  94. #define k_g_imask r6_bank /* r6_bank1 */
  95. #define current r7 /* r7_bank1 */
  96. /*
  97. * Kernel mode register usage:
  98. * k0 scratch
  99. * k1 scratch
  100. * k2 scratch (Exception code)
  101. * k3 scratch (Return address)
  102. * k4 scratch
  103. * k5 reserved
  104. * k6 Global Interrupt Mask (0--15 << 4)
  105. * k7 CURRENT_THREAD_INFO (pointer to current thread info)
  106. */
  107. !
  108. ! TLB Miss / Initial Page write exception handling
  109. ! _and_
  110. ! TLB hits, but the access violate the protection.
  111. ! It can be valid access, such as stack grow and/or C-O-W.
  112. !
  113. !
  114. ! Find the pmd/pte entry and loadtlb
  115. ! If it's not found, cause address error (SEGV)
  116. !
  117. ! Although this could be written in assembly language (and it'd be faster),
  118. ! this first version depends *much* on C implementation.
  119. !
  120. #define CLI() \
  121. stc sr, r0; \
  122. or #0xf0, r0; \
  123. ldc r0, sr
  124. #define STI() \
  125. mov.l __INV_IMASK, r11; \
  126. stc sr, r10; \
  127. and r11, r10; \
  128. stc k_g_imask, r11; \
  129. or r11, r10; \
  130. ldc r10, sr
  131. #if defined(CONFIG_PREEMPT)
  132. # define preempt_stop() CLI()
  133. #else
  134. # define preempt_stop()
  135. # define resume_kernel restore_all
  136. #endif
  137. #if defined(CONFIG_MMU)
  138. .align 2
  139. ENTRY(tlb_miss_load)
  140. bra call_dpf
  141. mov #0, r5
  142. .align 2
  143. ENTRY(tlb_miss_store)
  144. bra call_dpf
  145. mov #1, r5
  146. .align 2
  147. ENTRY(initial_page_write)
  148. bra call_dpf
  149. mov #1, r5
  150. .align 2
  151. ENTRY(tlb_protection_violation_load)
  152. bra call_dpf
  153. mov #0, r5
  154. .align 2
  155. ENTRY(tlb_protection_violation_store)
  156. bra call_dpf
  157. mov #1, r5
  158. call_dpf:
  159. mov.l 1f, r0
  160. mov r5, r8
  161. mov.l @r0, r6
  162. mov r6, r9
  163. mov.l 2f, r0
  164. sts pr, r10
  165. jsr @r0
  166. mov r15, r4
  167. !
  168. tst r0, r0
  169. bf/s 0f
  170. lds r10, pr
  171. rts
  172. nop
  173. 0: STI()
  174. mov.l 3f, r0
  175. mov r9, r6
  176. mov r8, r5
  177. jmp @r0
  178. mov r15, r4
  179. .align 2
  180. 1: .long MMU_TEA
  181. 2: .long __do_page_fault
  182. 3: .long do_page_fault
  183. .align 2
  184. ENTRY(address_error_load)
  185. bra call_dae
  186. mov #0,r5 ! writeaccess = 0
  187. .align 2
  188. ENTRY(address_error_store)
  189. bra call_dae
  190. mov #1,r5 ! writeaccess = 1
  191. .align 2
  192. call_dae:
  193. mov.l 1f, r0
  194. mov.l @r0, r6 ! address
  195. mov.l 2f, r0
  196. jmp @r0
  197. mov r15, r4 ! regs
  198. .align 2
  199. 1: .long MMU_TEA
  200. 2: .long do_address_error
  201. #endif /* CONFIG_MMU */
  202. #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
  203. ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
  204. ! If both are configured, handle the debug traps (breakpoints) in SW,
  205. ! but still allow BIOS traps to FW.
  206. .align 2
  207. debug_kernel:
  208. #if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
  209. /* Force BIOS call to FW (debug_trap put TRA in r8) */
  210. mov r8,r0
  211. shlr2 r0
  212. cmp/eq #0x3f,r0
  213. bt debug_kernel_fw
  214. #endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
  215. debug_enter:
  216. #if defined(CONFIG_SH_KGDB)
  217. /* Jump to kgdb, pass stacked regs as arg */
  218. debug_kernel_sw:
  219. mov.l 3f, r0
  220. jmp @r0
  221. mov r15, r4
  222. .align 2
  223. 3: .long kgdb_handle_exception
  224. #endif /* CONFIG_SH_KGDB */
  225. #if defined(CONFIG_SH_STANDARD_BIOS)
  226. /* Unwind the stack and jmp to the debug entry */
  227. debug_kernel_fw:
  228. mov.l @r15+, r0
  229. mov.l @r15+, r1
  230. mov.l @r15+, r2
  231. mov.l @r15+, r3
  232. mov.l @r15+, r4
  233. mov.l @r15+, r5
  234. mov.l @r15+, r6
  235. mov.l @r15+, r7
  236. stc sr, r8
  237. mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F
  238. or r9, r8
  239. ldc r8, sr ! here, change the register bank
  240. mov.l @r15+, r8
  241. mov.l @r15+, r9
  242. mov.l @r15+, r10
  243. mov.l @r15+, r11
  244. mov.l @r15+, r12
  245. mov.l @r15+, r13
  246. mov.l @r15+, r14
  247. mov.l @r15+, k0
  248. ldc.l @r15+, spc
  249. lds.l @r15+, pr
  250. mov.l @r15+, k1
  251. ldc.l @r15+, gbr
  252. lds.l @r15+, mach
  253. lds.l @r15+, macl
  254. mov k0, r15
  255. !
  256. mov.l 2f, k0
  257. mov.l @k0, k0
  258. jmp @k0
  259. ldc k1, ssr
  260. .align 2
  261. 1: .long 0x300000f0
  262. 2: .long gdb_vbr_vector
  263. #endif /* CONFIG_SH_STANDARD_BIOS */
  264. #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
  265. .align 2
  266. debug_trap:
  267. #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
  268. mov #OFF_SR, r0
  269. mov.l @(r0,r15), r0 ! get status register
  270. shll r0
  271. shll r0 ! kernel space?
  272. bt/s debug_kernel
  273. #endif
  274. mov.l @r15, r0 ! Restore R0 value
  275. mov.l 1f, r8
  276. jmp @r8
  277. nop
  278. .align 2
  279. ENTRY(exception_error)
  280. !
  281. STI()
  282. mov.l 2f, r0
  283. jmp @r0
  284. nop
  285. !
  286. .align 2
  287. 1: .long break_point_trap_software
  288. 2: .long do_exception_error
  289. .align 2
  290. ret_from_exception:
  291. preempt_stop()
  292. ret_from_irq:
  293. !
  294. mov #OFF_SR, r0
  295. mov.l @(r0,r15), r0 ! get status register
  296. shll r0
  297. shll r0 ! kernel space?
  298. bt/s resume_kernel ! Yes, it's from kernel, go back soon
  299. GET_THREAD_INFO(r8)
  300. #ifdef CONFIG_PREEMPT
  301. bra resume_userspace
  302. nop
  303. ENTRY(resume_kernel)
  304. mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
  305. tst r0, r0
  306. bf noresched
  307. need_resched:
  308. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  309. tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
  310. bt noresched
  311. mov #OFF_SR, r0
  312. mov.l @(r0,r15), r0 ! get status register
  313. and #0xf0, r0 ! interrupts off (exception path)?
  314. cmp/eq #0xf0, r0
  315. bt noresched
  316. mov.l 1f, r0
  317. mov.l r0, @(TI_PRE_COUNT,r8)
  318. STI()
  319. mov.l 2f, r0
  320. jsr @r0
  321. nop
  322. mov #0, r0
  323. mov.l r0, @(TI_PRE_COUNT,r8)
  324. CLI()
  325. bra need_resched
  326. nop
  327. noresched:
  328. bra restore_all
  329. nop
  330. .align 2
  331. 1: .long PREEMPT_ACTIVE
  332. 2: .long schedule
  333. #endif
  334. ENTRY(resume_userspace)
  335. ! r8: current_thread_info
  336. CLI()
  337. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  338. tst #_TIF_WORK_MASK, r0
  339. bt/s restore_all
  340. tst #_TIF_NEED_RESCHED, r0
  341. .align 2
  342. work_pending:
  343. ! r0: current_thread_info->flags
  344. ! r8: current_thread_info
  345. ! t: result of "tst #_TIF_NEED_RESCHED, r0"
  346. bf/s work_resched
  347. tst #_TIF_SIGPENDING, r0
  348. work_notifysig:
  349. bt/s restore_all
  350. mov r15, r4
  351. mov #0, r5
  352. mov.l 2f, r1
  353. mova restore_all, r0
  354. jmp @r1
  355. lds r0, pr
  356. work_resched:
  357. #ifndef CONFIG_PREEMPT
  358. ! gUSA handling
  359. mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
  360. mov r0, r1
  361. shll r0
  362. bf/s 1f
  363. shll r0
  364. bf/s 1f
  365. mov #OFF_PC, r0
  366. ! SP >= 0xc0000000 : gUSA mark
  367. mov.l @(r0,r15), r2 ! get user space PC (program counter)
  368. mov.l @(OFF_R0,r15), r3 ! end point
  369. cmp/hs r3, r2 ! r2 >= r3?
  370. bt 1f
  371. add r3, r1 ! rewind point #2
  372. mov.l r1, @(r0,r15) ! reset PC to rewind point #2
  373. !
  374. 1:
  375. #endif
  376. mov.l 1f, r1
  377. jsr @r1 ! schedule
  378. nop
  379. CLI()
  380. !
  381. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  382. tst #_TIF_WORK_MASK, r0
  383. bt restore_all
  384. bra work_pending
  385. tst #_TIF_NEED_RESCHED, r0
  386. .align 2
  387. 1: .long schedule
  388. 2: .long do_signal
  389. .align 2
  390. syscall_exit_work:
  391. ! r0: current_thread_info->flags
  392. ! r8: current_thread_info
  393. tst #_TIF_SYSCALL_TRACE, r0
  394. bt/s work_pending
  395. tst #_TIF_NEED_RESCHED, r0
  396. STI()
  397. ! XXX setup arguments...
  398. mov.l 4f, r0 ! do_syscall_trace
  399. jsr @r0
  400. nop
  401. bra resume_userspace
  402. nop
  403. .align 2
  404. syscall_trace_entry:
  405. ! Yes it is traced.
  406. ! XXX setup arguments...
  407. mov.l 4f, r11 ! Call do_syscall_trace which notifies
  408. jsr @r11 ! superior (will chomp R[0-7])
  409. nop
  410. ! Reload R0-R4 from kernel stack, where the
  411. ! parent may have modified them using
  412. ! ptrace(POKEUSR). (Note that R0-R2 are
  413. ! used by the system call handler directly
  414. ! from the kernel stack anyway, so don't need
  415. ! to be reloaded here.) This allows the parent
  416. ! to rewrite system calls and args on the fly.
  417. mov.l @(OFF_R4,r15), r4 ! arg0
  418. mov.l @(OFF_R5,r15), r5
  419. mov.l @(OFF_R6,r15), r6
  420. mov.l @(OFF_R7,r15), r7 ! arg3
  421. mov.l @(OFF_R3,r15), r3 ! syscall_nr
  422. ! Arrange for do_syscall_trace to be called
  423. ! again as the system call returns.
  424. mov.l 2f, r10 ! Number of syscalls
  425. cmp/hs r10, r3
  426. bf syscall_call
  427. mov #-ENOSYS, r0
  428. bra syscall_exit
  429. mov.l r0, @(OFF_R0,r15) ! Return value
  430. /*
  431. * Syscall interface:
  432. *
  433. * Syscall #: R3
  434. * Arguments #0 to #3: R4--R7
  435. * Arguments #4 to #6: R0, R1, R2
  436. * TRA: (number of arguments + 0x10) x 4
  437. *
  438. * This code also handles delegating other traps to the BIOS/gdb stub
  439. * according to:
  440. *
  441. * Trap number
  442. * (TRA>>2) Purpose
  443. * -------- -------
  444. * 0x0-0xf old syscall ABI
  445. * 0x10-0x1f new syscall ABI
  446. * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
  447. *
  448. * Note: When we're first called, the TRA value must be shifted
  449. * right 2 bits in order to get the value that was used as the "trapa"
  450. * argument.
  451. */
  452. .align 2
  453. .globl ret_from_fork
  454. ret_from_fork:
  455. mov.l 1f, r8
  456. jsr @r8
  457. mov r0, r4
  458. bra syscall_exit
  459. nop
  460. .align 2
  461. 1: .long schedule_tail
  462. !
  463. ENTRY(system_call)
  464. mov.l 1f, r9
  465. mov.l @r9, r8 ! Read from TRA (Trap Address) Register
  466. !
  467. ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
  468. mov #0x7f, r9
  469. cmp/hi r9, r8
  470. bt/s 0f
  471. mov #OFF_TRA, r9
  472. add r15, r9
  473. !
  474. mov.l r8, @r9 ! set TRA value to tra
  475. STI()
  476. ! Call the system call handler through the table.
  477. ! First check for bad syscall number
  478. mov r3, r9
  479. mov.l 2f, r8 ! Number of syscalls
  480. cmp/hs r8, r9
  481. bf/s good_system_call
  482. GET_THREAD_INFO(r8)
  483. syscall_badsys: ! Bad syscall number
  484. mov #-ENOSYS, r0
  485. bra resume_userspace
  486. mov.l r0, @(OFF_R0,r15) ! Return value
  487. !
  488. 0:
  489. bra debug_trap
  490. nop
  491. !
  492. good_system_call: ! Good syscall number
  493. mov.l @(TI_FLAGS,r8), r8
  494. mov #_TIF_SYSCALL_TRACE, r10
  495. tst r10, r8
  496. bf syscall_trace_entry
  497. !
  498. syscall_call:
  499. shll2 r9 ! x4
  500. mov.l 3f, r8 ! Load the address of sys_call_table
  501. add r8, r9
  502. mov.l @r9, r8
  503. jsr @r8 ! jump to specific syscall handler
  504. nop
  505. mov.l r0, @(OFF_R0,r15) ! save the return value
  506. !
  507. syscall_exit:
  508. CLI()
  509. !
  510. GET_THREAD_INFO(r8)
  511. mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
  512. tst #_TIF_ALLWORK_MASK, r0
  513. bf syscall_exit_work
  514. restore_all:
  515. mov.l @r15+, r0
  516. mov.l @r15+, r1
  517. mov.l @r15+, r2
  518. mov.l @r15+, r3
  519. mov.l @r15+, r4
  520. mov.l @r15+, r5
  521. mov.l @r15+, r6
  522. mov.l @r15+, r7
  523. !
  524. stc sr, r8
  525. mov.l 7f, r9
  526. or r9, r8 ! BL =1, RB=1
  527. ldc r8, sr ! here, change the register bank
  528. !
  529. mov.l @r15+, r8
  530. mov.l @r15+, r9
  531. mov.l @r15+, r10
  532. mov.l @r15+, r11
  533. mov.l @r15+, r12
  534. mov.l @r15+, r13
  535. mov.l @r15+, r14
  536. mov.l @r15+, k4 ! original stack pointer
  537. ldc.l @r15+, spc
  538. lds.l @r15+, pr
  539. mov.l @r15+, k3 ! original SR
  540. ldc.l @r15+, gbr
  541. lds.l @r15+, mach
  542. lds.l @r15+, macl
  543. add #4, r15 ! Skip syscall number
  544. !
  545. #ifdef CONFIG_SH_DSP
  546. mov.l @r15+, k0 ! DSP mode marker
  547. mov.l 5f, k1
  548. cmp/eq k0, k1 ! Do we have a DSP stack frame?
  549. bf skip_restore
  550. stc sr, k0 ! Enable CPU DSP mode
  551. or k1, k0 ! (within kernel it may be disabled)
  552. ldc k0, sr
  553. mov r2, k0 ! Backup r2
  554. ! Restore DSP registers from stack
  555. mov r15, r2
  556. movs.l @r2+, a1
  557. movs.l @r2+, a0g
  558. movs.l @r2+, a1g
  559. movs.l @r2+, m0
  560. movs.l @r2+, m1
  561. mov r2, r15
  562. lds.l @r15+, a0
  563. lds.l @r15+, x0
  564. lds.l @r15+, x1
  565. lds.l @r15+, y0
  566. lds.l @r15+, y1
  567. lds.l @r15+, dsr
  568. ldc.l @r15+, rs
  569. ldc.l @r15+, re
  570. ldc.l @r15+, mod
  571. mov k0, r2 ! Restore r2
  572. skip_restore:
  573. #endif
  574. !
  575. ! Calculate new SR value
  576. mov k3, k2 ! original SR value
  577. mov.l 9f, k1
  578. and k1, k2 ! Mask orignal SR value
  579. !
  580. mov k3, k0 ! Calculate IMASK-bits
  581. shlr2 k0
  582. and #0x3c, k0
  583. cmp/eq #0x3c, k0
  584. bt/s 6f
  585. shll2 k0
  586. mov g_imask, k0
  587. !
  588. 6: or k0, k2 ! Set the IMASK-bits
  589. ldc k2, ssr
  590. !
  591. #if defined(CONFIG_KGDB_NMI)
  592. ! Clear in_nmi
  593. mov.l 4f, k0
  594. mov #0, k1
  595. mov.b k1, @k0
  596. #endif
  597. mov.l @r15+, k2 ! restore EXPEVT
  598. mov k4, r15
  599. rte
  600. nop
  601. .align 2
  602. 1: .long TRA
  603. 2: .long NR_syscalls
  604. 3: .long sys_call_table
  605. 4: .long do_syscall_trace
  606. 5: .long 0x00001000 ! DSP
  607. 7: .long 0x30000000
  608. 9:
  609. __INV_IMASK:
  610. .long 0xffffff0f ! ~(IMASK)
  611. ! Exception Vector Base
  612. !
  613. ! Should be aligned page boundary.
  614. !
  615. .balign 4096,0,4096
  616. ENTRY(vbr_base)
  617. .long 0
  618. !
  619. .balign 256,0,256
  620. general_exception:
  621. mov.l 1f, k2
  622. mov.l 2f, k3
  623. bra handle_exception
  624. mov.l @k2, k2
  625. .align 2
  626. 1: .long EXPEVT
  627. 2: .long ret_from_exception
  628. !
  629. !
  630. .balign 1024,0,1024
  631. tlb_miss:
  632. mov.l 1f, k2
  633. mov.l 4f, k3
  634. bra handle_exception
  635. mov.l @k2, k2
  636. !
  637. .balign 512,0,512
  638. interrupt:
  639. mov.l 2f, k2
  640. mov.l 3f, k3
  641. #if defined(CONFIG_KGDB_NMI)
  642. ! Debounce (filter nested NMI)
  643. mov.l @k2, k0
  644. mov.l 5f, k1
  645. cmp/eq k1, k0
  646. bf 0f
  647. mov.l 6f, k1
  648. tas.b @k1
  649. bt 0f
  650. rte
  651. nop
  652. .align 2
  653. 5: .long NMI_VEC
  654. 6: .long in_nmi
  655. 0:
  656. #endif /* defined(CONFIG_KGDB_NMI) */
  657. bra handle_exception
  658. mov.l @k2, k2
  659. .align 2
  660. 1: .long EXPEVT
  661. 2: .long INTEVT
  662. 3: .long ret_from_irq
  663. 4: .long ret_from_exception
  664. !
  665. !
  666. .align 2
  667. handle_exception:
  668. ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
  669. ! save all registers onto stack.
  670. !
  671. stc ssr, k0 ! Is it from kernel space?
  672. shll k0 ! Check MD bit (bit30) by shifting it into...
  673. shll k0 ! ...the T bit
  674. bt/s 1f ! It's a kernel to kernel transition.
  675. mov r15, k0 ! save original stack to k0
  676. /* User space to kernel */
  677. mov #0x20, k1
  678. shll8 k1 ! k1 := 8192 (== THREAD_SIZE)
  679. add current, k1
  680. mov k1, r15 ! change to kernel stack
  681. !
  682. 1: mov #-1, k4
  683. mov.l 2f, k1
  684. !
  685. #ifdef CONFIG_SH_DSP
  686. mov.l r2, @-r15 ! Save r2, we need another reg
  687. stc sr, k4
  688. mov.l 1f, r2
  689. tst r2, k4 ! Check if in DSP mode
  690. mov.l @r15+, r2 ! Restore r2 now
  691. bt/s skip_save
  692. mov #0, k4 ! Set marker for no stack frame
  693. mov r2, k4 ! Backup r2 (in k4) for later
  694. ! Save DSP registers on stack
  695. stc.l mod, @-r15
  696. stc.l re, @-r15
  697. stc.l rs, @-r15
  698. sts.l dsr, @-r15
  699. sts.l y1, @-r15
  700. sts.l y0, @-r15
  701. sts.l x1, @-r15
  702. sts.l x0, @-r15
  703. sts.l a0, @-r15
  704. ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr.
  705. ! FIXME: Make sure that this is still the case with newer toolchains,
  706. ! as we're not at all interested in supporting ancient toolchains at
  707. ! this point. -- PFM.
  708. mov r15, r2
  709. .word 0xf653 ! movs.l a1, @-r2
  710. .word 0xf6f3 ! movs.l a0g, @-r2
  711. .word 0xf6d3 ! movs.l a1g, @-r2
  712. .word 0xf6c3 ! movs.l m0, @-r2
  713. .word 0xf6e3 ! movs.l m1, @-r2
  714. mov r2, r15
  715. mov k4, r2 ! Restore r2
  716. mov.l 1f, k4 ! Force DSP stack frame
  717. skip_save:
  718. mov.l k4, @-r15 ! Push DSP mode marker onto stack
  719. #endif
  720. ! Save the user registers on the stack.
  721. mov.l k2, @-r15 ! EXPEVT
  722. mov.l k4, @-r15 ! set TRA (default: -1)
  723. !
  724. sts.l macl, @-r15
  725. sts.l mach, @-r15
  726. stc.l gbr, @-r15
  727. stc.l ssr, @-r15
  728. sts.l pr, @-r15
  729. stc.l spc, @-r15
  730. !
  731. lds k3, pr ! Set the return address to pr
  732. !
  733. mov.l k0, @-r15 ! save orignal stack
  734. mov.l r14, @-r15
  735. mov.l r13, @-r15
  736. mov.l r12, @-r15
  737. mov.l r11, @-r15
  738. mov.l r10, @-r15
  739. mov.l r9, @-r15
  740. mov.l r8, @-r15
  741. !
  742. stc sr, r8 ! Back to normal register bank, and
  743. or k1, r8 ! Block all interrupts
  744. mov.l 3f, k1
  745. and k1, r8 ! ...
  746. ldc r8, sr ! ...changed here.
  747. !
  748. mov.l r7, @-r15
  749. mov.l r6, @-r15
  750. mov.l r5, @-r15
  751. mov.l r4, @-r15
  752. mov.l r3, @-r15
  753. mov.l r2, @-r15
  754. mov.l r1, @-r15
  755. mov.l r0, @-r15
  756. ! Then, dispatch to the handler, according to the exception code.
  757. stc k_ex_code, r8
  758. shlr2 r8
  759. shlr r8
  760. mov.l 4f, r9
  761. add r8, r9
  762. mov.l @r9, r9
  763. jmp @r9
  764. nop
  765. .align 2
  766. 1: .long 0x00001000 ! DSP=1
  767. 2: .long 0x000080f0 ! FD=1, IMASK=15
  768. 3: .long 0xcfffffff ! RB=0, BL=0
  769. 4: .long exception_handling_table
  770. .align 2
  771. ENTRY(exception_none)
  772. rts
  773. nop