entry-avr32b.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. /*
  2. * Copyright (C) 2004-2006 Atmel Corporation
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. /*
  9. * This file contains the low-level entry-points into the kernel, that is,
  10. * exception handlers, debug trap handlers, interrupt handlers and the
  11. * system call handler.
  12. */
  13. #include <linux/errno.h>
  14. #include <asm/asm.h>
  15. #include <asm/hardirq.h>
  16. #include <asm/irq.h>
  17. #include <asm/ocd.h>
  18. #include <asm/page.h>
  19. #include <asm/pgtable.h>
  20. #include <asm/ptrace.h>
  21. #include <asm/sysreg.h>
  22. #include <asm/thread_info.h>
  23. #include <asm/unistd.h>
  24. #ifdef CONFIG_PREEMPT
  25. # define preempt_stop mask_interrupts
  26. #else
  27. # define preempt_stop
  28. # define fault_resume_kernel fault_restore_all
  29. #endif
  30. #define __MASK(x) ((1 << (x)) - 1)
  31. #define IRQ_MASK ((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \
  32. (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT))
  33. .section .ex.text,"ax",@progbits
  34. .align 2
  35. exception_vectors:
  36. bral handle_critical
  37. .align 2
  38. bral handle_critical
  39. .align 2
  40. bral do_bus_error_write
  41. .align 2
  42. bral do_bus_error_read
  43. .align 2
  44. bral do_nmi_ll
  45. .align 2
  46. bral handle_address_fault
  47. .align 2
  48. bral handle_protection_fault
  49. .align 2
  50. bral handle_debug
  51. .align 2
  52. bral do_illegal_opcode_ll
  53. .align 2
  54. bral do_illegal_opcode_ll
  55. .align 2
  56. bral do_illegal_opcode_ll
  57. .align 2
  58. bral do_fpe_ll
  59. .align 2
  60. bral do_illegal_opcode_ll
  61. .align 2
  62. bral handle_address_fault
  63. .align 2
  64. bral handle_address_fault
  65. .align 2
  66. bral handle_protection_fault
  67. .align 2
  68. bral handle_protection_fault
  69. .align 2
  70. bral do_dtlb_modified
  71. /*
  72. * r0 : PGD/PT/PTE
  73. * r1 : Offending address
  74. * r2 : Scratch register
  75. * r3 : Cause (5, 12 or 13)
  76. */
  77. #define tlbmiss_save pushm r0-r3
  78. #define tlbmiss_restore popm r0-r3
  79. .section .tlbx.ex.text,"ax",@progbits
  80. .global itlb_miss
  81. itlb_miss:
  82. tlbmiss_save
  83. rjmp tlb_miss_common
  84. .section .tlbr.ex.text,"ax",@progbits
  85. dtlb_miss_read:
  86. tlbmiss_save
  87. rjmp tlb_miss_common
  88. .section .tlbw.ex.text,"ax",@progbits
  89. dtlb_miss_write:
  90. tlbmiss_save
  91. .global tlb_miss_common
  92. tlb_miss_common:
  93. mfsr r0, SYSREG_PTBR
  94. mfsr r1, SYSREG_TLBEAR
  95. /* Is it the vmalloc space? */
  96. bld r1, 31
  97. brcs handle_vmalloc_miss
  98. /* First level lookup */
  99. pgtbl_lookup:
  100. lsr r2, r1, PGDIR_SHIFT
  101. ld.w r0, r0[r2 << 2]
  102. bld r0, _PAGE_BIT_PRESENT
  103. brcc page_table_not_present
  104. /* TODO: Check access rights on page table if necessary */
  105. /* Translate to virtual address in P1. */
  106. andl r0, 0xf000
  107. sbr r0, 31
  108. /* Second level lookup */
  109. lsl r1, (32 - PGDIR_SHIFT)
  110. lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
  111. add r2, r0, r1 << 2
  112. ld.w r1, r2[0]
  113. bld r1, _PAGE_BIT_PRESENT
  114. brcc page_not_present
  115. /* Mark the page as accessed */
  116. sbr r1, _PAGE_BIT_ACCESSED
  117. st.w r2[0], r1
  118. /* Drop software flags */
  119. andl r1, _PAGE_FLAGS_HARDWARE_MASK & 0xffff
  120. mtsr SYSREG_TLBELO, r1
  121. /* Figure out which entry we want to replace */
  122. mfsr r0, SYSREG_TLBARLO
  123. clz r2, r0
  124. brcc 1f
  125. mov r1, -1 /* All entries have been accessed, */
  126. mtsr SYSREG_TLBARLO, r1 /* so reset TLBAR */
  127. mov r2, 0 /* and start at 0 */
  128. 1: mfsr r1, SYSREG_MMUCR
  129. lsl r2, 14
  130. andl r1, 0x3fff, COH
  131. or r1, r2
  132. mtsr SYSREG_MMUCR, r1
  133. tlbw
  134. tlbmiss_restore
  135. rete
  136. handle_vmalloc_miss:
  137. /* Simply do the lookup in init's page table */
  138. mov r0, lo(swapper_pg_dir)
  139. orh r0, hi(swapper_pg_dir)
  140. rjmp pgtbl_lookup
  141. /* --- System Call --- */
  142. .section .scall.text,"ax",@progbits
  143. system_call:
  144. pushm r12 /* r12_orig */
  145. stmts --sp, r0-lr
  146. zero_fp
  147. mfsr r0, SYSREG_RAR_SUP
  148. mfsr r1, SYSREG_RSR_SUP
  149. stm --sp, r0-r1
  150. /* check for syscall tracing */
  151. get_thread_info r0
  152. ld.w r1, r0[TI_flags]
  153. bld r1, TIF_SYSCALL_TRACE
  154. brcs syscall_trace_enter
  155. syscall_trace_cont:
  156. cp.w r8, NR_syscalls
  157. brhs syscall_badsys
  158. lddpc lr, syscall_table_addr
  159. ld.w lr, lr[r8 << 2]
  160. mov r8, r5 /* 5th argument (6th is pushed by stub) */
  161. icall lr
  162. .global syscall_return
  163. syscall_return:
  164. get_thread_info r0
  165. mask_interrupts /* make sure we don't miss an interrupt
  166. setting need_resched or sigpending
  167. between sampling and the rets */
  168. /* Store the return value so that the correct value is loaded below */
  169. stdsp sp[REG_R12], r12
  170. ld.w r1, r0[TI_flags]
  171. andl r1, _TIF_ALLWORK_MASK, COH
  172. brne syscall_exit_work
  173. syscall_exit_cont:
  174. popm r8-r9
  175. mtsr SYSREG_RAR_SUP, r8
  176. mtsr SYSREG_RSR_SUP, r9
  177. ldmts sp++, r0-lr
  178. sub sp, -4 /* r12_orig */
  179. rets
  180. .align 2
  181. syscall_table_addr:
  182. .long sys_call_table
  183. syscall_badsys:
  184. mov r12, -ENOSYS
  185. rjmp syscall_return
  186. .global ret_from_fork
  187. ret_from_fork:
  188. rcall schedule_tail
  189. /* check for syscall tracing */
  190. get_thread_info r0
  191. ld.w r1, r0[TI_flags]
  192. andl r1, _TIF_ALLWORK_MASK, COH
  193. brne syscall_exit_work
  194. rjmp syscall_exit_cont
  195. syscall_trace_enter:
  196. pushm r8-r12
  197. rcall syscall_trace
  198. popm r8-r12
  199. rjmp syscall_trace_cont
  200. syscall_exit_work:
  201. bld r1, TIF_SYSCALL_TRACE
  202. brcc 1f
  203. unmask_interrupts
  204. rcall syscall_trace
  205. mask_interrupts
  206. ld.w r1, r0[TI_flags]
  207. 1: bld r1, TIF_NEED_RESCHED
  208. brcc 2f
  209. unmask_interrupts
  210. rcall schedule
  211. mask_interrupts
  212. ld.w r1, r0[TI_flags]
  213. rjmp 1b
  214. 2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
  215. tst r1, r2
  216. breq 3f
  217. unmask_interrupts
  218. mov r12, sp
  219. mov r11, r0
  220. rcall do_notify_resume
  221. mask_interrupts
  222. ld.w r1, r0[TI_flags]
  223. rjmp 1b
  224. 3: bld r1, TIF_BREAKPOINT
  225. brcc syscall_exit_cont
  226. mfsr r3, SYSREG_TLBEHI
  227. lddsp r2, sp[REG_PC]
  228. andl r3, 0xff, COH
  229. lsl r3, 1
  230. sbr r3, 30
  231. sbr r3, 0
  232. mtdr DBGREG_BWA2A, r2
  233. mtdr DBGREG_BWC2A, r3
  234. rjmp syscall_exit_cont
  235. /* The slow path of the TLB miss handler */
  236. page_table_not_present:
  237. page_not_present:
  238. tlbmiss_restore
  239. sub sp, 4
  240. stmts --sp, r0-lr
  241. rcall save_full_context_ex
  242. mfsr r12, SYSREG_ECR
  243. mov r11, sp
  244. rcall do_page_fault
  245. rjmp ret_from_exception
  246. /* This function expects to find offending PC in SYSREG_RAR_EX */
  247. save_full_context_ex:
  248. mfsr r8, SYSREG_RSR_EX
  249. mov r12, r8
  250. andh r8, (MODE_MASK >> 16), COH
  251. mfsr r11, SYSREG_RAR_EX
  252. brne 2f
  253. 1: pushm r11, r12 /* PC and SR */
  254. unmask_exceptions
  255. ret r12
  256. 2: sub r10, sp, -(FRAME_SIZE_FULL - REG_LR)
  257. stdsp sp[4], r10 /* replace saved SP */
  258. rjmp 1b
  259. /* Low-level exception handlers */
  260. handle_critical:
  261. pushm r12
  262. pushm r0-r12
  263. rcall save_full_context_ex
  264. mfsr r12, SYSREG_ECR
  265. mov r11, sp
  266. rcall do_critical_exception
  267. /* We should never get here... */
  268. bad_return:
  269. sub r12, pc, (. - 1f)
  270. bral panic
  271. .align 2
  272. 1: .asciz "Return from critical exception!"
  273. .align 1
  274. do_bus_error_write:
  275. sub sp, 4
  276. stmts --sp, r0-lr
  277. rcall save_full_context_ex
  278. mov r11, 1
  279. rjmp 1f
  280. do_bus_error_read:
  281. sub sp, 4
  282. stmts --sp, r0-lr
  283. rcall save_full_context_ex
  284. mov r11, 0
  285. 1: mfsr r12, SYSREG_BEAR
  286. mov r10, sp
  287. rcall do_bus_error
  288. rjmp ret_from_exception
  289. .align 1
  290. do_nmi_ll:
  291. sub sp, 4
  292. stmts --sp, r0-lr
  293. /* FIXME: Make sure RAR_NMI and RSR_NMI are pushed instead of *_EX */
  294. rcall save_full_context_ex
  295. mfsr r12, SYSREG_ECR
  296. mov r11, sp
  297. rcall do_nmi
  298. rjmp bad_return
  299. handle_address_fault:
  300. sub sp, 4
  301. stmts --sp, r0-lr
  302. rcall save_full_context_ex
  303. mfsr r12, SYSREG_ECR
  304. mov r11, sp
  305. rcall do_address_exception
  306. rjmp ret_from_exception
  307. handle_protection_fault:
  308. sub sp, 4
  309. stmts --sp, r0-lr
  310. rcall save_full_context_ex
  311. mfsr r12, SYSREG_ECR
  312. mov r11, sp
  313. rcall do_page_fault
  314. rjmp ret_from_exception
  315. .align 1
  316. do_illegal_opcode_ll:
  317. sub sp, 4
  318. stmts --sp, r0-lr
  319. rcall save_full_context_ex
  320. mfsr r12, SYSREG_ECR
  321. mov r11, sp
  322. rcall do_illegal_opcode
  323. rjmp ret_from_exception
  324. do_dtlb_modified:
  325. pushm r0-r3
  326. mfsr r1, SYSREG_TLBEAR
  327. mfsr r0, SYSREG_PTBR
  328. lsr r2, r1, PGDIR_SHIFT
  329. ld.w r0, r0[r2 << 2]
  330. lsl r1, (32 - PGDIR_SHIFT)
  331. lsr r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT
  332. /* Translate to virtual address in P1 */
  333. andl r0, 0xf000
  334. sbr r0, 31
  335. add r2, r0, r1 << 2
  336. ld.w r3, r2[0]
  337. sbr r3, _PAGE_BIT_DIRTY
  338. mov r0, r3
  339. st.w r2[0], r3
  340. /* The page table is up-to-date. Update the TLB entry as well */
  341. andl r0, lo(_PAGE_FLAGS_HARDWARE_MASK)
  342. mtsr SYSREG_TLBELO, r0
  343. /* MMUCR[DRP] is updated automatically, so let's go... */
  344. tlbw
  345. popm r0-r3
  346. rete
  347. do_fpe_ll:
  348. sub sp, 4
  349. stmts --sp, r0-lr
  350. rcall save_full_context_ex
  351. unmask_interrupts
  352. mov r12, 26
  353. mov r11, sp
  354. rcall do_fpe
  355. rjmp ret_from_exception
  356. ret_from_exception:
  357. mask_interrupts
  358. lddsp r4, sp[REG_SR]
  359. andh r4, (MODE_MASK >> 16), COH
  360. brne fault_resume_kernel
  361. get_thread_info r0
  362. ld.w r1, r0[TI_flags]
  363. andl r1, _TIF_WORK_MASK, COH
  364. brne fault_exit_work
  365. fault_resume_user:
  366. popm r8-r9
  367. mask_exceptions
  368. mtsr SYSREG_RAR_EX, r8
  369. mtsr SYSREG_RSR_EX, r9
  370. ldmts sp++, r0-lr
  371. sub sp, -4
  372. rete
  373. fault_resume_kernel:
  374. #ifdef CONFIG_PREEMPT
  375. get_thread_info r0
  376. ld.w r2, r0[TI_preempt_count]
  377. cp.w r2, 0
  378. brne 1f
  379. ld.w r1, r0[TI_flags]
  380. bld r1, TIF_NEED_RESCHED
  381. brcc 1f
  382. lddsp r4, sp[REG_SR]
  383. bld r4, SYSREG_GM_OFFSET
  384. brcs 1f
  385. rcall preempt_schedule_irq
  386. 1:
  387. #endif
  388. popm r8-r9
  389. mask_exceptions
  390. mfsr r1, SYSREG_SR
  391. mtsr SYSREG_RAR_EX, r8
  392. mtsr SYSREG_RSR_EX, r9
  393. popm lr
  394. sub sp, -4 /* ignore SP */
  395. popm r0-r12
  396. sub sp, -4 /* ignore r12_orig */
  397. rete
  398. irq_exit_work:
  399. /* Switch to exception mode so that we can share the same code. */
  400. mfsr r8, SYSREG_SR
  401. cbr r8, SYSREG_M0_OFFSET
  402. orh r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2))
  403. mtsr SYSREG_SR, r8
  404. sub pc, -2
  405. get_thread_info r0
  406. ld.w r1, r0[TI_flags]
  407. fault_exit_work:
  408. bld r1, TIF_NEED_RESCHED
  409. brcc 1f
  410. unmask_interrupts
  411. rcall schedule
  412. mask_interrupts
  413. ld.w r1, r0[TI_flags]
  414. rjmp fault_exit_work
  415. 1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
  416. tst r1, r2
  417. breq 2f
  418. unmask_interrupts
  419. mov r12, sp
  420. mov r11, r0
  421. rcall do_notify_resume
  422. mask_interrupts
  423. ld.w r1, r0[TI_flags]
  424. rjmp fault_exit_work
  425. 2: bld r1, TIF_BREAKPOINT
  426. brcc fault_resume_user
  427. mfsr r3, SYSREG_TLBEHI
  428. lddsp r2, sp[REG_PC]
  429. andl r3, 0xff, COH
  430. lsl r3, 1
  431. sbr r3, 30
  432. sbr r3, 0
  433. mtdr DBGREG_BWA2A, r2
  434. mtdr DBGREG_BWC2A, r3
  435. rjmp fault_resume_user
  436. /* If we get a debug trap from privileged context we end up here */
  437. handle_debug_priv:
  438. /* Fix up LR and SP in regs. r11 contains the mode we came from */
  439. mfsr r8, SYSREG_SR
  440. mov r9, r8
  441. andh r8, hi(~MODE_MASK)
  442. or r8, r11
  443. mtsr SYSREG_SR, r8
  444. sub pc, -2
  445. stdsp sp[REG_LR], lr
  446. mtsr SYSREG_SR, r9
  447. sub pc, -2
  448. sub r10, sp, -FRAME_SIZE_FULL
  449. stdsp sp[REG_SP], r10
  450. mov r12, sp
  451. rcall do_debug_priv
  452. /* Now, put everything back */
  453. ssrf SR_EM_BIT
  454. popm r10, r11
  455. mtsr SYSREG_RAR_DBG, r10
  456. mtsr SYSREG_RSR_DBG, r11
  457. mfsr r8, SYSREG_SR
  458. mov r9, r8
  459. andh r8, hi(~MODE_MASK)
  460. andh r11, hi(MODE_MASK)
  461. or r8, r11
  462. mtsr SYSREG_SR, r8
  463. sub pc, -2
  464. popm lr
  465. mtsr SYSREG_SR, r9
  466. sub pc, -2
  467. sub sp, -4 /* skip SP */
  468. popm r0-r12
  469. sub sp, -4
  470. retd
  471. /*
  472. * At this point, everything is masked, that is, interrupts,
  473. * exceptions and debugging traps. We might get called from
  474. * interrupt or exception context in some rare cases, but this
  475. * will be taken care of by do_debug(), so we're not going to
  476. * do a 100% correct context save here.
  477. */
  478. handle_debug:
  479. sub sp, 4 /* r12_orig */
  480. stmts --sp, r0-lr
  481. mfsr r10, SYSREG_RAR_DBG
  482. mfsr r11, SYSREG_RSR_DBG
  483. unmask_exceptions
  484. pushm r10,r11
  485. andh r11, (MODE_MASK >> 16), COH
  486. brne handle_debug_priv
  487. mov r12, sp
  488. rcall do_debug
  489. lddsp r10, sp[REG_SR]
  490. andh r10, (MODE_MASK >> 16), COH
  491. breq debug_resume_user
  492. debug_restore_all:
  493. popm r10,r11
  494. mask_exceptions
  495. mtsr SYSREG_RSR_DBG, r11
  496. mtsr SYSREG_RAR_DBG, r10
  497. ldmts sp++, r0-lr
  498. sub sp, -4
  499. retd
  500. debug_resume_user:
  501. get_thread_info r0
  502. mask_interrupts
  503. ld.w r1, r0[TI_flags]
  504. andl r1, _TIF_DBGWORK_MASK, COH
  505. breq debug_restore_all
  506. 1: bld r1, TIF_NEED_RESCHED
  507. brcc 2f
  508. unmask_interrupts
  509. rcall schedule
  510. mask_interrupts
  511. ld.w r1, r0[TI_flags]
  512. rjmp 1b
  513. 2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK
  514. tst r1, r2
  515. breq 3f
  516. unmask_interrupts
  517. mov r12, sp
  518. mov r11, r0
  519. rcall do_notify_resume
  520. mask_interrupts
  521. ld.w r1, r0[TI_flags]
  522. rjmp 1b
  523. 3: bld r1, TIF_SINGLE_STEP
  524. brcc debug_restore_all
  525. mfdr r2, DBGREG_DC
  526. sbr r2, DC_SS_BIT
  527. mtdr DBGREG_DC, r2
  528. rjmp debug_restore_all
  529. .set rsr_int0, SYSREG_RSR_INT0
  530. .set rsr_int1, SYSREG_RSR_INT1
  531. .set rsr_int2, SYSREG_RSR_INT2
  532. .set rsr_int3, SYSREG_RSR_INT3
  533. .set rar_int0, SYSREG_RAR_INT0
  534. .set rar_int1, SYSREG_RAR_INT1
  535. .set rar_int2, SYSREG_RAR_INT2
  536. .set rar_int3, SYSREG_RAR_INT3
  537. .macro IRQ_LEVEL level
  538. .type irq_level\level, @function
  539. irq_level\level:
  540. sub sp, 4 /* r12_orig */
  541. stmts --sp,r0-lr
  542. mfsr r8, rar_int\level
  543. mfsr r9, rsr_int\level
  544. pushm r8-r9
  545. mov r11, sp
  546. mov r12, \level
  547. rcall do_IRQ
  548. lddsp r4, sp[REG_SR]
  549. andh r4, (MODE_MASK >> 16), COH
  550. #ifdef CONFIG_PREEMPT
  551. brne 2f
  552. #else
  553. brne 1f
  554. #endif
  555. get_thread_info r0
  556. ld.w r1, r0[TI_flags]
  557. andl r1, _TIF_WORK_MASK, COH
  558. brne irq_exit_work
  559. 1: popm r8-r9
  560. mtsr rar_int\level, r8
  561. mtsr rsr_int\level, r9
  562. ldmts sp++,r0-lr
  563. sub sp, -4 /* ignore r12_orig */
  564. rete
  565. #ifdef CONFIG_PREEMPT
  566. 2:
  567. get_thread_info r0
  568. ld.w r2, r0[TI_preempt_count]
  569. cp.w r2, 0
  570. brne 1b
  571. ld.w r1, r0[TI_flags]
  572. bld r1, TIF_NEED_RESCHED
  573. brcc 1b
  574. lddsp r4, sp[REG_SR]
  575. bld r4, SYSREG_GM_OFFSET
  576. brcs 1b
  577. rcall preempt_schedule_irq
  578. rjmp 1b
  579. #endif
  580. .endm
  581. .section .irq.text,"ax",@progbits
  582. .global irq_level0
  583. .global irq_level1
  584. .global irq_level2
  585. .global irq_level3
  586. IRQ_LEVEL 0
  587. IRQ_LEVEL 1
  588. IRQ_LEVEL 2
  589. IRQ_LEVEL 3