entry.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  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. /* how to get the thread information struct from ASM */
  115. #define GET_THREAD_INFO(reg) GET_THREAD_INFO reg
  116. .macro GET_THREAD_INFO reg
  117. ldi \reg, #-THREAD_SIZE
  118. and \reg, sp
  119. .endm
  120. ENTRY(ret_from_fork)
  121. pop r0
  122. bl schedule_tail
  123. GET_THREAD_INFO(r8)
  124. bra syscall_exit
  125. /*
  126. * Return to user mode is not as complex as all this looks,
  127. * but we want the default path for a system call return to
  128. * go as quickly as possible which is why some of this is
  129. * less clear than it otherwise should be.
  130. */
  131. ; userspace resumption stub bypassing syscall exit tracing
  132. ALIGN
  133. ret_from_exception:
  134. preempt_stop(r4)
  135. ret_from_intr:
  136. ld r4, PSW(sp)
  137. #ifdef CONFIG_ISA_M32R2
  138. and3 r4, r4, #0x8800 ; check BSM and BPM bits
  139. #else
  140. and3 r4, r4, #0x8000 ; check BSM bit
  141. #endif
  142. beqz r4, resume_kernel
  143. resume_userspace:
  144. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  145. ; setting need_resched or sigpending
  146. ; between sampling and the iret
  147. GET_THREAD_INFO(r8)
  148. ld r9, @(TI_FLAGS, r8)
  149. and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done on
  150. ; int/exception return?
  151. bnez r4, work_pending
  152. bra restore_all
  153. #ifdef CONFIG_PREEMPT
  154. ENTRY(resume_kernel)
  155. GET_THREAD_INFO(r8)
  156. ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
  157. bnez r9, restore_all
  158. need_resched:
  159. ld r9, @(TI_FLAGS, r8) ; need_resched set ?
  160. and3 r4, r9, #_TIF_NEED_RESCHED
  161. beqz r4, restore_all
  162. ld r4, PSW(sp) ; interrupts off (exception path) ?
  163. and3 r4, r4, #0x4000
  164. beqz r4, restore_all
  165. LDIMM (r4, PREEMPT_ACTIVE)
  166. st r4, @(TI_PRE_COUNT, r8)
  167. ENABLE_INTERRUPTS(r4)
  168. bl schedule
  169. ldi r4, #0
  170. st r4, @(TI_PRE_COUNT, r8)
  171. DISABLE_INTERRUPTS(r4)
  172. bra need_resched
  173. #endif
  174. ; system call handler stub
  175. ENTRY(system_call)
  176. SWITCH_TO_KERNEL_STACK
  177. SAVE_ALL
  178. ENABLE_INTERRUPTS(r4) ; Enable interrupt
  179. st sp, PTREGS(sp) ; implicit pt_regs parameter
  180. cmpui r7, #NR_syscalls
  181. bnc syscall_badsys
  182. st r7, SYSCALL_NR(sp) ; syscall_nr
  183. ; system call tracing in operation
  184. GET_THREAD_INFO(r8)
  185. ld r9, @(TI_FLAGS, r8)
  186. and3 r4, r9, #_TIF_SYSCALL_TRACE
  187. bnez r4, syscall_trace_entry
  188. syscall_call:
  189. slli r7, #2 ; table jump for the system call
  190. LDIMM (r4, sys_call_table)
  191. add r7, r4
  192. ld r7, @r7
  193. jl r7 ; execute system call
  194. st r0, R0(sp) ; save the return value
  195. syscall_exit:
  196. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  197. ; setting need_resched or sigpending
  198. ; between sampling and the iret
  199. ld r9, @(TI_FLAGS, r8)
  200. and3 r4, r9, #_TIF_ALLWORK_MASK ; current->work
  201. bnez r4, syscall_exit_work
  202. restore_all:
  203. RESTORE_ALL
  204. # perform work that needs to be done immediately before resumption
  205. # r9 : flags
  206. ALIGN
  207. work_pending:
  208. and3 r4, r9, #_TIF_NEED_RESCHED
  209. beqz r4, work_notifysig
  210. work_resched:
  211. bl schedule
  212. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  213. ; setting need_resched or sigpending
  214. ; between sampling and the iret
  215. ld r9, @(TI_FLAGS, r8)
  216. and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done other
  217. ; than syscall tracing?
  218. beqz r4, restore_all
  219. and3 r4, r4, #_TIF_NEED_RESCHED
  220. bnez r4, work_resched
  221. work_notifysig: ; deal with pending signals and
  222. ; notify-resume requests
  223. mv r0, sp ; arg1 : struct pt_regs *regs
  224. ldi r1, #0 ; arg2 : sigset_t *oldset
  225. mv r2, r9 ; arg3 : __u32 thread_info_flags
  226. bl do_notify_resume
  227. bra restore_all
  228. ; perform syscall exit tracing
  229. ALIGN
  230. syscall_trace_entry:
  231. ldi r4, #-ENOSYS
  232. st r4, R0(sp)
  233. bl do_syscall_trace
  234. ld r0, ORIG_R0(sp)
  235. ld r1, R1(sp)
  236. ld r2, R2(sp)
  237. ld r3, R3(sp)
  238. ld r4, R4(sp)
  239. ld r5, R5(sp)
  240. ld r6, R6(sp)
  241. ld r7, SYSCALL_NR(sp)
  242. cmpui r7, #NR_syscalls
  243. bc syscall_call
  244. bra syscall_exit
  245. ; perform syscall exit tracing
  246. ALIGN
  247. syscall_exit_work:
  248. ld r9, @(TI_FLAGS, r8)
  249. and3 r4, r9, #_TIF_SYSCALL_TRACE
  250. beqz r4, work_pending
  251. ENABLE_INTERRUPTS(r4) ; could let do_syscall_trace() call
  252. ; schedule() instead
  253. bl do_syscall_trace
  254. bra resume_userspace
  255. ALIGN
  256. syscall_fault:
  257. SAVE_ALL
  258. GET_THREAD_INFO(r8)
  259. ldi r4, #-EFAULT
  260. st r4, R0(sp)
  261. bra resume_userspace
  262. ALIGN
  263. syscall_badsys:
  264. ldi r4, #-ENOSYS
  265. st r4, R0(sp)
  266. bra resume_userspace
  267. .global eit_vector
  268. .equ ei_vec_table, eit_vector + 0x0200
  269. /*
  270. * EI handler routine
  271. */
  272. ENTRY(ei_handler)
  273. #if defined(CONFIG_CHIP_M32700)
  274. ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
  275. SWITCH_TO_KERNEL_STACK
  276. #endif
  277. SAVE_ALL
  278. mv r1, sp ; arg1(regs)
  279. ; get ICU status
  280. seth r0, #shigh(M32R_ICU_ISTS_ADDR)
  281. ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
  282. push r0
  283. #if defined(CONFIG_SMP)
  284. /*
  285. * If IRQ == 0 --> Nothing to do, Not write IMASK
  286. * If IRQ == IPI --> Do IPI handler, Not write IMASK
  287. * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK
  288. */
  289. slli r0, #4
  290. srli r0, #24 ; r0(irq_num<<2)
  291. ;; IRQ exist check
  292. #if defined(CONFIG_CHIP_M32700)
  293. /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
  294. bnez r0, 0f
  295. ld24 r14, #0x00070000
  296. seth r0, #shigh(M32R_ICU_IMASK_ADDR)
  297. st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
  298. bra 1f
  299. .fillinsn
  300. 0:
  301. #endif /* CONFIG_CHIP_M32700 */
  302. beqz r0, 1f ; if (!irq_num) goto exit
  303. ;; IPI check
  304. cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
  305. bc 2f
  306. cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check
  307. bnc 2f
  308. LDIMM (r2, ei_vec_table)
  309. add r2, r0
  310. ld r2, @r2
  311. beqz r2, 1f ; if (no IPI handler) goto exit
  312. mv r0, r1 ; arg0(regs)
  313. jl r2
  314. .fillinsn
  315. 1:
  316. addi sp, #4
  317. bra restore_all
  318. .fillinsn
  319. 2:
  320. srli r0, #2
  321. #else /* not CONFIG_SMP */
  322. srli r0, #22 ; r0(irq)
  323. #endif /* not CONFIG_SMP */
  324. #if defined(CONFIG_PLAT_HAS_INT1ICU)
  325. add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
  326. bnez r2, 3f
  327. seth r0, #shigh(M32R_INT1ICU_ISTS)
  328. lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN
  329. slli r0, #21
  330. srli r0, #27 ; ISN
  331. addi r0, #(M32R_INT1ICU_IRQ_BASE)
  332. bra check_end
  333. .fillinsn
  334. 3:
  335. #endif /* CONFIG_PLAT_HAS_INT1ICU */
  336. #if defined(CONFIG_PLAT_HAS_INT0ICU)
  337. add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
  338. bnez r2, 4f
  339. seth r0, #shigh(M32R_INT0ICU_ISTS)
  340. lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN
  341. slli r0, #21
  342. srli r0, #27 ; ISN
  343. add3 r0, r0, #(M32R_INT0ICU_IRQ_BASE)
  344. bra check_end
  345. .fillinsn
  346. 4:
  347. #endif /* CONFIG_PLAT_HAS_INT0ICU */
  348. #if defined(CONFIG_PLAT_HAS_INT2ICU)
  349. add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
  350. bnez r2, 5f
  351. seth r0, #shigh(M32R_INT2ICU_ISTS)
  352. lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN
  353. slli r0, #21
  354. srli r0, #27 ; ISN
  355. add3 r0, r0, #(M32R_INT2ICU_IRQ_BASE)
  356. ; bra check_end
  357. .fillinsn
  358. 5:
  359. #endif /* CONFIG_PLAT_HAS_INT2ICU */
  360. check_end:
  361. bl do_IRQ
  362. pop r14
  363. seth r0, #shigh(M32R_ICU_IMASK_ADDR)
  364. st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
  365. bra ret_from_intr
  366. /*
  367. * Default EIT handler
  368. */
  369. ALIGN
  370. int_msg:
  371. .asciz "Unknown interrupt\n"
  372. .byte 0
  373. ENTRY(default_eit_handler)
  374. push r0
  375. mvfc r0, psw
  376. push r1
  377. push r2
  378. push r3
  379. push r0
  380. LDIMM (r0, __KERNEL_DS)
  381. mv r0, r1
  382. mv r0, r2
  383. LDIMM (r0, int_msg)
  384. bl printk
  385. pop r0
  386. pop r3
  387. pop r2
  388. pop r1
  389. mvtc r0, psw
  390. pop r0
  391. infinit:
  392. bra infinit
  393. #ifdef CONFIG_MMU
  394. /*
  395. * Access Exception handler
  396. */
  397. ENTRY(ace_handler)
  398. SWITCH_TO_KERNEL_STACK
  399. SAVE_ALL
  400. seth r2, #shigh(MMU_REG_BASE) /* Check status register */
  401. ld r4, @(low(MESTS_offset),r2)
  402. st r4, @(low(MESTS_offset),r2)
  403. srl3 r1, r4, #4
  404. #ifdef CONFIG_CHIP_M32700
  405. and3 r1, r1, #0x0000ffff
  406. ; WORKAROUND: ignore TME bit for the M32700(TS1).
  407. #endif /* CONFIG_CHIP_M32700 */
  408. beqz r1, inst
  409. oprand:
  410. ld r2, @(low(MDEVA_offset),r2) ; set address
  411. srli r1, #1
  412. bra 1f
  413. inst:
  414. and3 r1, r4, #2
  415. srli r1, #1
  416. or3 r1, r1, #8
  417. mvfc r2, bpc ; set address
  418. .fillinsn
  419. 1:
  420. mvfc r3, psw
  421. mv r0, sp
  422. and3 r3, r3, 0x800
  423. srli r3, #9
  424. or r1, r3
  425. /*
  426. * do_page_fault():
  427. * r0 : struct pt_regs *regs
  428. * r1 : unsigned long error-code
  429. * r2 : unsigned long address
  430. * error-code:
  431. * +------+------+------+------+
  432. * | bit3 | bit2 | bit1 | bit0 |
  433. * +------+------+------+------+
  434. * bit 3 == 0:means data, 1:means instruction
  435. * bit 2 == 0:means kernel, 1:means user-mode
  436. * bit 1 == 0:means read, 1:means write
  437. * bit 0 == 0:means no page found 1:means protection fault
  438. *
  439. */
  440. bl do_page_fault
  441. bra ret_from_intr
  442. #endif /* CONFIG_MMU */
  443. ENTRY(alignment_check)
  444. /* void alignment_check(int error_code) */
  445. SWITCH_TO_KERNEL_STACK
  446. SAVE_ALL
  447. ldi r1, #0x30 ; error_code
  448. mv r0, sp ; pt_regs
  449. bl do_alignment_check
  450. error_code:
  451. bra ret_from_exception
  452. ENTRY(rie_handler)
  453. /* void rie_handler(int error_code) */
  454. SWITCH_TO_KERNEL_STACK
  455. SAVE_ALL
  456. ldi r1, #0x20 ; error_code
  457. mv r0, sp ; pt_regs
  458. bl do_rie_handler
  459. bra error_code
  460. ENTRY(pie_handler)
  461. /* void pie_handler(int error_code) */
  462. SWITCH_TO_KERNEL_STACK
  463. SAVE_ALL
  464. ldi r1, #0 ; error_code ; FIXME
  465. mv r0, sp ; pt_regs
  466. bl do_pie_handler
  467. bra error_code
  468. ENTRY(debug_trap)
  469. /* void debug_trap(void) */
  470. .global withdraw_debug_trap
  471. SWITCH_TO_KERNEL_STACK
  472. SAVE_ALL
  473. mv r0, sp ; pt_regs
  474. bl withdraw_debug_trap
  475. ldi r1, #0 ; error_code
  476. mv r0, sp ; pt_regs
  477. bl do_debug_trap
  478. bra error_code
  479. ENTRY(ill_trap)
  480. /* void ill_trap(void) */
  481. SWITCH_TO_KERNEL_STACK
  482. SAVE_ALL
  483. ldi r1, #0 ; error_code ; FIXME
  484. mv r0, sp ; pt_regs
  485. bl do_ill_trap
  486. bra error_code
  487. ENTRY(cache_flushing_handler)
  488. /* void _flush_cache_all(void); */
  489. .global _flush_cache_all
  490. SWITCH_TO_KERNEL_STACK
  491. push r0
  492. push r1
  493. push r2
  494. push r3
  495. push r4
  496. push r5
  497. push r6
  498. push r7
  499. push lr
  500. bl _flush_cache_all
  501. pop lr
  502. pop r7
  503. pop r6
  504. pop r5
  505. pop r4
  506. pop r3
  507. pop r2
  508. pop r1
  509. pop r0
  510. rte
  511. .section .rodata,"a"
  512. #include "syscall_table.S"
  513. syscall_table_size=(.-sys_call_table)