entry.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /*
  2. * linux/arch/m32r/kernel/entry.S
  3. *
  4. * Copyright (c) 2001, 2002 Hirokazu Takata, Hitoshi Yamamoto, H. Kondo
  5. * Copyright (c) 2003 Hitoshi Yamamoto
  6. * Copyright (c) 2004 Hirokazu Takata <takata at linux-m32r.org>
  7. *
  8. * Taken from i386 version.
  9. * Copyright (C) 1991, 1992 Linus Torvalds
  10. */
  11. /*
  12. * entry.S contains the system-call and fault low-level handling routines.
  13. * This also contains the timer-interrupt handler, as well as all interrupts
  14. * and faults that can result in a task-switch.
  15. *
  16. * NOTE: This code handles signal-recognition, which happens every time
  17. * after a timer-interrupt and after each system call.
  18. *
  19. * Stack layout in 'ret_from_system_call':
  20. * ptrace needs to have all regs on the stack.
  21. * if the order here is changed, it needs to be
  22. * updated in fork.c:copy_thread, signal.c:do_signal,
  23. * ptrace.c and ptrace.h
  24. *
  25. * M32R/M32Rx/M32R2
  26. * @(sp) - r4
  27. * @(0x04,sp) - r5
  28. * @(0x08,sp) - r6
  29. * @(0x0c,sp) - *pt_regs
  30. * @(0x10,sp) - r0
  31. * @(0x14,sp) - r1
  32. * @(0x18,sp) - r2
  33. * @(0x1c,sp) - r3
  34. * @(0x20,sp) - r7
  35. * @(0x24,sp) - r8
  36. * @(0x28,sp) - r9
  37. * @(0x2c,sp) - r10
  38. * @(0x30,sp) - r11
  39. * @(0x34,sp) - r12
  40. * @(0x38,sp) - syscall_nr
  41. * @(0x3c,sp) - acc0h
  42. * @(0x40,sp) - acc0l
  43. * @(0x44,sp) - acc1h ; ISA_DSP_LEVEL2 only
  44. * @(0x48,sp) - acc1l ; ISA_DSP_LEVEL2 only
  45. * @(0x4c,sp) - psw
  46. * @(0x50,sp) - bpc
  47. * @(0x54,sp) - bbpsw
  48. * @(0x58,sp) - bbpc
  49. * @(0x5c,sp) - spu (cr3)
  50. * @(0x60,sp) - fp (r13)
  51. * @(0x64,sp) - lr (r14)
  52. * @(0x68,sp) - spi (cr2)
  53. * @(0x6c,sp) - orig_r0
  54. */
  55. #include <linux/linkage.h>
  56. #include <asm/irq.h>
  57. #include <asm/unistd.h>
  58. #include <asm/assembler.h>
  59. #include <asm/thread_info.h>
  60. #include <asm/errno.h>
  61. #include <asm/segment.h>
  62. #include <asm/smp.h>
  63. #include <asm/page.h>
  64. #include <asm/m32r.h>
  65. #include <asm/mmu_context.h>
  66. #if !defined(CONFIG_MMU)
  67. #define sys_madvise sys_ni_syscall
  68. #define sys_readahead sys_ni_syscall
  69. #define sys_mprotect sys_ni_syscall
  70. #define sys_msync sys_ni_syscall
  71. #define sys_mlock sys_ni_syscall
  72. #define sys_munlock sys_ni_syscall
  73. #define sys_mlockall sys_ni_syscall
  74. #define sys_munlockall sys_ni_syscall
  75. #define sys_mremap sys_ni_syscall
  76. #define sys_mincore sys_ni_syscall
  77. #define sys_remap_file_pages sys_ni_syscall
  78. #endif /* CONFIG_MMU */
  79. #define R4(reg) @reg
  80. #define R5(reg) @(0x04,reg)
  81. #define R6(reg) @(0x08,reg)
  82. #define PTREGS(reg) @(0x0C,reg)
  83. #define R0(reg) @(0x10,reg)
  84. #define R1(reg) @(0x14,reg)
  85. #define R2(reg) @(0x18,reg)
  86. #define R3(reg) @(0x1C,reg)
  87. #define R7(reg) @(0x20,reg)
  88. #define R8(reg) @(0x24,reg)
  89. #define R9(reg) @(0x28,reg)
  90. #define R10(reg) @(0x2C,reg)
  91. #define R11(reg) @(0x30,reg)
  92. #define R12(reg) @(0x34,reg)
  93. #define SYSCALL_NR(reg) @(0x38,reg)
  94. #define ACC0H(reg) @(0x3C,reg)
  95. #define ACC0L(reg) @(0x40,reg)
  96. #define ACC1H(reg) @(0x44,reg)
  97. #define ACC1L(reg) @(0x48,reg)
  98. #define PSW(reg) @(0x4C,reg)
  99. #define BPC(reg) @(0x50,reg)
  100. #define BBPSW(reg) @(0x54,reg)
  101. #define BBPC(reg) @(0x58,reg)
  102. #define SPU(reg) @(0x5C,reg)
  103. #define FP(reg) @(0x60,reg) /* FP = R13 */
  104. #define LR(reg) @(0x64,reg)
  105. #define SP(reg) @(0x68,reg)
  106. #define ORIG_R0(reg) @(0x6C,reg)
  107. #define nr_syscalls ((syscall_table_size)/4)
  108. #ifdef CONFIG_PREEMPT
  109. #define preempt_stop(x) DISABLE_INTERRUPTS(x)
  110. #else
  111. #define preempt_stop(x)
  112. #define resume_kernel restore_all
  113. #endif
  114. ENTRY(ret_from_fork)
  115. pop r0
  116. bl schedule_tail
  117. GET_THREAD_INFO(r8)
  118. bra syscall_exit
  119. /*
  120. * Return to user mode is not as complex as all this looks,
  121. * but we want the default path for a system call return to
  122. * go as quickly as possible which is why some of this is
  123. * less clear than it otherwise should be.
  124. */
  125. ; userspace resumption stub bypassing syscall exit tracing
  126. ALIGN
  127. ret_from_exception:
  128. preempt_stop(r4)
  129. ret_from_intr:
  130. ld r4, PSW(sp)
  131. #ifdef CONFIG_ISA_M32R2
  132. and3 r4, r4, #0x8800 ; check BSM and BPM bits
  133. #else
  134. and3 r4, r4, #0x8000 ; check BSM bit
  135. #endif
  136. beqz r4, resume_kernel
  137. resume_userspace:
  138. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  139. ; setting need_resched or sigpending
  140. ; between sampling and the iret
  141. GET_THREAD_INFO(r8)
  142. ld r9, @(TI_FLAGS, r8)
  143. and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done on
  144. ; int/exception return?
  145. bnez r4, work_pending
  146. bra restore_all
  147. #ifdef CONFIG_PREEMPT
  148. ENTRY(resume_kernel)
  149. GET_THREAD_INFO(r8)
  150. ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
  151. bnez r9, restore_all
  152. need_resched:
  153. ld r9, @(TI_FLAGS, r8) ; need_resched set ?
  154. and3 r4, r9, #_TIF_NEED_RESCHED
  155. beqz r4, restore_all
  156. ld r4, PSW(sp) ; interrupts off (exception path) ?
  157. and3 r4, r4, #0x4000
  158. beqz r4, restore_all
  159. LDIMM (r4, PREEMPT_ACTIVE)
  160. st r4, @(TI_PRE_COUNT, r8)
  161. ENABLE_INTERRUPTS(r4)
  162. bl schedule
  163. ldi r4, #0
  164. st r4, @(TI_PRE_COUNT, r8)
  165. DISABLE_INTERRUPTS(r4)
  166. bra need_resched
  167. #endif
  168. ; system call handler stub
  169. ENTRY(system_call)
  170. SWITCH_TO_KERNEL_STACK
  171. SAVE_ALL
  172. ENABLE_INTERRUPTS(r4) ; Enable interrupt
  173. st sp, PTREGS(sp) ; implicit pt_regs parameter
  174. cmpui r7, #NR_syscalls
  175. bnc syscall_badsys
  176. st r7, SYSCALL_NR(sp) ; syscall_nr
  177. ; system call tracing in operation
  178. GET_THREAD_INFO(r8)
  179. ld r9, @(TI_FLAGS, r8)
  180. and3 r4, r9, #_TIF_SYSCALL_TRACE
  181. bnez r4, syscall_trace_entry
  182. syscall_call:
  183. slli r7, #2 ; table jump for the system call
  184. LDIMM (r4, sys_call_table)
  185. add r7, r4
  186. ld r7, @r7
  187. jl r7 ; execute system call
  188. st r0, R0(sp) ; save the return value
  189. syscall_exit:
  190. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  191. ; setting need_resched or sigpending
  192. ; between sampling and the iret
  193. ld r9, @(TI_FLAGS, r8)
  194. and3 r4, r9, #_TIF_ALLWORK_MASK ; current->work
  195. bnez r4, syscall_exit_work
  196. restore_all:
  197. RESTORE_ALL
  198. # perform work that needs to be done immediately before resumption
  199. # r9 : flags
  200. ALIGN
  201. work_pending:
  202. and3 r4, r9, #_TIF_NEED_RESCHED
  203. beqz r4, work_notifysig
  204. work_resched:
  205. bl schedule
  206. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  207. ; setting need_resched or sigpending
  208. ; between sampling and the iret
  209. ld r9, @(TI_FLAGS, r8)
  210. and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done other
  211. ; than syscall tracing?
  212. beqz r4, restore_all
  213. and3 r4, r4, #_TIF_NEED_RESCHED
  214. bnez r4, work_resched
  215. work_notifysig: ; deal with pending signals and
  216. ; notify-resume requests
  217. mv r0, sp ; arg1 : struct pt_regs *regs
  218. ldi r1, #0 ; arg2 : sigset_t *oldset
  219. mv r2, r9 ; arg3 : __u32 thread_info_flags
  220. bl do_notify_resume
  221. bra restore_all
  222. ; perform syscall exit tracing
  223. ALIGN
  224. syscall_trace_entry:
  225. ldi r4, #-ENOSYS
  226. st r4, R0(sp)
  227. bl do_syscall_trace
  228. ld r0, ORIG_R0(sp)
  229. ld r1, R1(sp)
  230. ld r2, R2(sp)
  231. ld r3, R3(sp)
  232. ld r4, R4(sp)
  233. ld r5, R5(sp)
  234. ld r6, R6(sp)
  235. ld r7, SYSCALL_NR(sp)
  236. cmpui r7, #NR_syscalls
  237. bc syscall_call
  238. bra syscall_exit
  239. ; perform syscall exit tracing
  240. ALIGN
  241. syscall_exit_work:
  242. ld r9, @(TI_FLAGS, r8)
  243. and3 r4, r9, #_TIF_SYSCALL_TRACE
  244. beqz r4, work_pending
  245. ENABLE_INTERRUPTS(r4) ; could let do_syscall_trace() call
  246. ; schedule() instead
  247. bl do_syscall_trace
  248. bra resume_userspace
  249. ALIGN
  250. syscall_fault:
  251. SAVE_ALL
  252. GET_THREAD_INFO(r8)
  253. ldi r4, #-EFAULT
  254. st r4, R0(sp)
  255. bra resume_userspace
  256. ALIGN
  257. syscall_badsys:
  258. ldi r4, #-ENOSYS
  259. st r4, R0(sp)
  260. bra resume_userspace
  261. .global eit_vector
  262. .equ ei_vec_table, eit_vector + 0x0200
  263. /*
  264. * EI handler routine
  265. */
  266. ENTRY(ei_handler)
  267. #if defined(CONFIG_CHIP_M32700)
  268. ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
  269. SWITCH_TO_KERNEL_STACK
  270. #endif
  271. SAVE_ALL
  272. mv r1, sp ; arg1(regs)
  273. ; get ICU status
  274. seth r0, #shigh(M32R_ICU_ISTS_ADDR)
  275. ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
  276. push r0
  277. #if defined(CONFIG_SMP)
  278. /*
  279. * If IRQ == 0 --> Nothing to do, Not write IMASK
  280. * If IRQ == IPI --> Do IPI handler, Not write IMASK
  281. * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK
  282. */
  283. slli r0, #4
  284. srli r0, #24 ; r0(irq_num<<2)
  285. ;; IRQ exist check
  286. #if defined(CONFIG_CHIP_M32700)
  287. /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
  288. bnez r0, 0f
  289. ld24 r14, #0x00070000
  290. seth r0, #shigh(M32R_ICU_IMASK_ADDR)
  291. st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
  292. bra 1f
  293. .fillinsn
  294. 0:
  295. #endif /* CONFIG_CHIP_M32700 */
  296. beqz r0, 1f ; if (!irq_num) goto exit
  297. ;; IPI check
  298. cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
  299. bc 2f
  300. cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check
  301. bnc 2f
  302. LDIMM (r2, ei_vec_table)
  303. add r2, r0
  304. ld r2, @r2
  305. beqz r2, 1f ; if (no IPI handler) goto exit
  306. mv r0, r1 ; arg0(regs)
  307. jl r2
  308. .fillinsn
  309. 1:
  310. addi sp, #4
  311. bra restore_all
  312. .fillinsn
  313. 2:
  314. srli r0, #2
  315. #else /* not CONFIG_SMP */
  316. srli r0, #22 ; r0(irq)
  317. #endif /* not CONFIG_SMP */
  318. #if defined(CONFIG_PLAT_HAS_INT1ICU)
  319. add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
  320. bnez r2, 3f
  321. seth r0, #shigh(M32R_INT1ICU_ISTS)
  322. lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN
  323. slli r0, #21
  324. srli r0, #27 ; ISN
  325. addi r0, #(M32R_INT1ICU_IRQ_BASE)
  326. bra check_end
  327. .fillinsn
  328. 3:
  329. #endif /* CONFIG_PLAT_HAS_INT1ICU */
  330. #if defined(CONFIG_PLAT_HAS_INT0ICU)
  331. add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
  332. bnez r2, 4f
  333. seth r0, #shigh(M32R_INT0ICU_ISTS)
  334. lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN
  335. slli r0, #21
  336. srli r0, #27 ; ISN
  337. add3 r0, r0, #(M32R_INT0ICU_IRQ_BASE)
  338. bra check_end
  339. .fillinsn
  340. 4:
  341. #endif /* CONFIG_PLAT_HAS_INT0ICU */
  342. #if defined(CONFIG_PLAT_HAS_INT2ICU)
  343. add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
  344. bnez r2, 5f
  345. seth r0, #shigh(M32R_INT2ICU_ISTS)
  346. lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN
  347. slli r0, #21
  348. srli r0, #27 ; ISN
  349. add3 r0, r0, #(M32R_INT2ICU_IRQ_BASE)
  350. ; bra check_end
  351. .fillinsn
  352. 5:
  353. #endif /* CONFIG_PLAT_HAS_INT2ICU */
  354. check_end:
  355. bl do_IRQ
  356. pop r14
  357. seth r0, #shigh(M32R_ICU_IMASK_ADDR)
  358. st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
  359. bra ret_from_intr
  360. /*
  361. * Default EIT handler
  362. */
  363. ALIGN
  364. int_msg:
  365. .asciz "Unknown interrupt\n"
  366. .byte 0
  367. ENTRY(default_eit_handler)
  368. push r0
  369. mvfc r0, psw
  370. push r1
  371. push r2
  372. push r3
  373. push r0
  374. LDIMM (r0, __KERNEL_DS)
  375. mv r0, r1
  376. mv r0, r2
  377. LDIMM (r0, int_msg)
  378. bl printk
  379. pop r0
  380. pop r3
  381. pop r2
  382. pop r1
  383. mvtc r0, psw
  384. pop r0
  385. infinit:
  386. bra infinit
  387. #ifdef CONFIG_MMU
  388. /*
  389. * Access Exception handler
  390. */
  391. ENTRY(ace_handler)
  392. SWITCH_TO_KERNEL_STACK
  393. SAVE_ALL
  394. seth r2, #shigh(MMU_REG_BASE) /* Check status register */
  395. ld r4, @(low(MESTS_offset),r2)
  396. st r4, @(low(MESTS_offset),r2)
  397. srl3 r1, r4, #4
  398. #ifdef CONFIG_CHIP_M32700
  399. and3 r1, r1, #0x0000ffff
  400. ; WORKAROUND: ignore TME bit for the M32700(TS1).
  401. #endif /* CONFIG_CHIP_M32700 */
  402. beqz r1, inst
  403. oprand:
  404. ld r2, @(low(MDEVA_offset),r2) ; set address
  405. srli r1, #1
  406. bra 1f
  407. inst:
  408. and3 r1, r4, #2
  409. srli r1, #1
  410. or3 r1, r1, #8
  411. mvfc r2, bpc ; set address
  412. .fillinsn
  413. 1:
  414. mvfc r3, psw
  415. mv r0, sp
  416. and3 r3, r3, 0x800
  417. srli r3, #9
  418. or r1, r3
  419. /*
  420. * do_page_fault():
  421. * r0 : struct pt_regs *regs
  422. * r1 : unsigned long error-code
  423. * r2 : unsigned long address
  424. * error-code:
  425. * +------+------+------+------+
  426. * | bit3 | bit2 | bit1 | bit0 |
  427. * +------+------+------+------+
  428. * bit 3 == 0:means data, 1:means instruction
  429. * bit 2 == 0:means kernel, 1:means user-mode
  430. * bit 1 == 0:means read, 1:means write
  431. * bit 0 == 0:means no page found 1:means protection fault
  432. *
  433. */
  434. bl do_page_fault
  435. bra ret_from_intr
  436. #endif /* CONFIG_MMU */
  437. ENTRY(alignment_check)
  438. /* void alignment_check(int error_code) */
  439. SWITCH_TO_KERNEL_STACK
  440. SAVE_ALL
  441. ldi r1, #0x30 ; error_code
  442. mv r0, sp ; pt_regs
  443. bl do_alignment_check
  444. error_code:
  445. bra ret_from_exception
  446. ENTRY(rie_handler)
  447. /* void rie_handler(int error_code) */
  448. SWITCH_TO_KERNEL_STACK
  449. SAVE_ALL
  450. ldi r1, #0x20 ; error_code
  451. mv r0, sp ; pt_regs
  452. bl do_rie_handler
  453. bra error_code
  454. ENTRY(pie_handler)
  455. /* void pie_handler(int error_code) */
  456. SWITCH_TO_KERNEL_STACK
  457. SAVE_ALL
  458. ldi r1, #0 ; error_code ; FIXME
  459. mv r0, sp ; pt_regs
  460. bl do_pie_handler
  461. bra error_code
  462. ENTRY(debug_trap)
  463. /* void debug_trap(void) */
  464. .global withdraw_debug_trap
  465. SWITCH_TO_KERNEL_STACK
  466. SAVE_ALL
  467. mv r0, sp ; pt_regs
  468. bl withdraw_debug_trap
  469. ldi r1, #0 ; error_code
  470. mv r0, sp ; pt_regs
  471. bl do_debug_trap
  472. bra error_code
  473. ENTRY(ill_trap)
  474. /* void ill_trap(void) */
  475. SWITCH_TO_KERNEL_STACK
  476. SAVE_ALL
  477. ldi r1, #0 ; error_code ; FIXME
  478. mv r0, sp ; pt_regs
  479. bl do_ill_trap
  480. bra error_code
  481. ENTRY(cache_flushing_handler)
  482. /* void _flush_cache_all(void); */
  483. .global _flush_cache_all
  484. SWITCH_TO_KERNEL_STACK
  485. push r0
  486. push r1
  487. push r2
  488. push r3
  489. push r4
  490. push r5
  491. push r6
  492. push r7
  493. push lr
  494. bl _flush_cache_all
  495. pop lr
  496. pop r7
  497. pop r6
  498. pop r5
  499. pop r4
  500. pop r3
  501. pop r2
  502. pop r1
  503. pop r0
  504. rte
  505. .section .rodata,"a"
  506. #include "syscall_table.S"
  507. syscall_table_size=(.-sys_call_table)